15738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/****************************************************************************** 25738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * 35738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * Copyright (C) 2004-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 the L2CAP 1.2 Flow Control and retransmissions 225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * functions 235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * 245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ******************************************************************************/ 255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 26f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He#include <base/logging.h> 27ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton#include <stdio.h> 285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include <stdlib.h> 295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include <string.h> 305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 31258c2538e3b62a8cdb403f2730c45d721e5292b4Pavlin Radoslavov#include "bt_common.h" 32911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#include "bt_types.h" 33911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#include "btm_api.h" 34911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#include "btm_int.h" 35911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#include "btu.h" 365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "hcimsgs.h" 375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "l2c_api.h" 38ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton#include "l2c_int.h" 39ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton#include "l2cdefs.h" 405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 41911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonextern fixed_queue_t* btu_general_alarm_queue; 4278bcff79e1b1f0efce436b33bdd6da88745bfc8aPavlin Radoslavov 439ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson/* Flag passed to retransmit_i_frames() when all packets should be retransmitted 449ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson */ 45911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#define L2C_FCR_RETX_ALL_PKTS 0xFF 465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 472e3d006b96eafb0651fe7f78d28250faf89405dePavlin Radoslavov/* this is the minimal offset required by OBX to process incoming packets */ 482e3d006b96eafb0651fe7f78d28250faf89405dePavlin Radoslavovstatic const uint16_t OBX_BUF_MIN_OFFSET = 4; 492e3d006b96eafb0651fe7f78d28250faf89405dePavlin Radoslavov 50911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic const char* SAR_types[] = {"Unsegmented", "Start", "End", 51911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "Continuation"}; 52911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic const char* SUP_types[] = {"RR", "REJ", "RNR", "SREJ"}; 535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/* Look-up table for the CRC calculation */ 555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic const unsigned short crctab[256] = { 56911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241, 0xc601, 57911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440, 0xcc01, 0x0cc0, 58911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40, 0x0a00, 0xcac1, 0xcb81, 59911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841, 0xd801, 0x18c0, 0x1980, 0xd941, 60911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 0x1b00, 0xdbc1, 0xda81, 0x1a40, 0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 61911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 0x1dc0, 0x1c80, 0xdc41, 0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 62911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 0x1680, 0xd641, 0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 63911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 0x1040, 0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240, 64911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441, 0x3c00, 65911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41, 0xfa01, 0x3ac0, 66911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840, 0x2800, 0xe8c1, 0xe981, 67911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41, 0xee01, 0x2ec0, 0x2f80, 0xef41, 68911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 0x2d00, 0xedc1, 0xec81, 0x2c40, 0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 69911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 0xe7c1, 0xe681, 0x2640, 0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 70911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 0x2080, 0xe041, 0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 71911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 0x6240, 0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441, 72911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41, 0xaa01, 73911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840, 0x7800, 0xb8c1, 74911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41, 0xbe01, 0x7ec0, 0x7f80, 75911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40, 0xb401, 0x74c0, 0x7580, 0xb541, 76911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 0x7700, 0xb7c1, 0xb681, 0x7640, 0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 77911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 0x71c0, 0x7080, 0xb041, 0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 78911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 0x5280, 0x9241, 0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 79911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 0x5440, 0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40, 80911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841, 0x8801, 81911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40, 0x4e00, 0x8ec1, 82911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41, 0x4400, 0x84c1, 0x8581, 83911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641, 0x8201, 0x42c0, 0x4380, 0x8341, 84911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 0x4100, 0x81c1, 0x8081, 0x4040, 855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}; 865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 88ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Static local functions 895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*/ 90911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic bool process_reqseq(tL2C_CCB* p_ccb, uint16_t ctrl_word); 91911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic void process_s_frame(tL2C_CCB* p_ccb, BT_HDR* p_buf, uint16_t ctrl_word); 92911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic void process_i_frame(tL2C_CCB* p_ccb, BT_HDR* p_buf, uint16_t ctrl_word, 93911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson bool delay_ack); 94911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic bool retransmit_i_frames(tL2C_CCB* p_ccb, uint8_t tx_seq); 95911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic void prepare_I_frame(tL2C_CCB* p_ccb, BT_HDR* p_buf, 96911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson bool is_retransmission); 97911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic void process_stream_frame(tL2C_CCB* p_ccb, BT_HDR* p_buf); 98911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic bool do_sar_reassembly(tL2C_CCB* p_ccb, BT_HDR* p_buf, 99911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t ctrl_word); 1005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ERTM_STATS == TRUE) 102911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic void l2c_fcr_collect_ack_delay(tL2C_CCB* p_ccb, uint8_t num_bufs_acked); 1035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif 1045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 106ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 107ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2c_fcr_updcrc 108ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 109ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description This function computes the CRC using the look-up table. 110ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 111ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns CRC 112ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 113ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 114911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic unsigned short l2c_fcr_updcrc(unsigned short icrc, unsigned char* icp, 115911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson int icnt) { 116911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson unsigned short crc = icrc; 117911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson unsigned char* cp = icp; 118911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson int cnt = icnt; 1195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 120911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson while (cnt--) { 121911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson crc = ((crc >> 8) & 0xff) ^ crctab[(crc & 0xff) ^ *cp++]; 122911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 124911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (crc); 1255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 1265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 128ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 129ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2c_fcr_tx_get_fcs 130ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 131ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description This function computes the CRC for a frame to be TXed. 132ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 133ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns CRC 134ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 135ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 136911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic uint16_t l2c_fcr_tx_get_fcs(BT_HDR* p_buf) { 137911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t* p = ((uint8_t*)(p_buf + 1)) + p_buf->offset; 1385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 139911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (l2c_fcr_updcrc(L2CAP_FCR_INIT_CRC, p, p_buf->len)); 1405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 1415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 143ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 144ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2c_fcr_rx_get_fcs 145ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 146ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description This function computes the CRC for a received frame. 147ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 148ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns CRC 149ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 150ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 151911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic uint16_t l2c_fcr_rx_get_fcs(BT_HDR* p_buf) { 152911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t* p = ((uint8_t*)(p_buf + 1)) + p_buf->offset; 1535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 154911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* offset points past the L2CAP header, but the CRC check includes it */ 155911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p -= L2CAP_PKT_OVERHEAD; 1565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 157911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return ( 158911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_fcr_updcrc(L2CAP_FCR_INIT_CRC, p, p_buf->len + L2CAP_PKT_OVERHEAD)); 1595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 1605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 162ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 163ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2c_fcr_start_timer 164ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 165ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description This function starts the (monitor or retransmission) timer. 166ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 167ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns - 168ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 169ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 170911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2c_fcr_start_timer(tL2C_CCB* p_ccb) { 171f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(p_ccb != NULL); 172911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint32_t tout; 173911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 174911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* The timers which are in milliseconds */ 175911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->fcrb.wait_ack) { 176911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tout = (uint32_t)p_ccb->our_cfg.fcr.mon_tout; 177911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 178911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tout = (uint32_t)p_ccb->our_cfg.fcr.rtrans_tout; 179911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 180911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 181911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Only start a timer that was not started */ 182911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (!alarm_is_scheduled(p_ccb->fcrb.mon_retrans_timer)) { 183911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson alarm_set_on_queue(p_ccb->fcrb.mon_retrans_timer, tout, 184911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_ccb_timer_timeout, p_ccb, btu_general_alarm_queue); 185911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 1875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 189ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 190ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2c_fcr_stop_timer 191ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 192ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description This function stops the (monitor or transmission) timer. 193ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 194ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns - 195ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 196ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 197911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2c_fcr_stop_timer(tL2C_CCB* p_ccb) { 198f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(p_ccb != NULL); 199911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson alarm_cancel(p_ccb->fcrb.mon_retrans_timer); 2005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 2015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 203ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 204ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2c_fcr_cleanup 205ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2069ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Description This function cleans up the variable used for 2079ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * flow-control/retrans. 208ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 209ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns - 210ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 211ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 212911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2c_fcr_cleanup(tL2C_CCB* p_ccb) { 213f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(p_ccb != NULL); 214911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tL2C_FCRB* p_fcrb = &p_ccb->fcrb; 2155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 216911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson alarm_free(p_fcrb->mon_retrans_timer); 217911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_fcrb->mon_retrans_timer = NULL; 218911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson alarm_free(p_fcrb->ack_timer); 219911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_fcrb->ack_timer = NULL; 2205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 221911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson osi_free_and_reset((void**)&p_fcrb->p_rx_sdu); 2225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 223911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson fixed_queue_free(p_fcrb->waiting_for_ack_q, osi_free); 224911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_fcrb->waiting_for_ack_q = NULL; 2255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 226911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson fixed_queue_free(p_fcrb->srej_rcv_hold_q, osi_free); 227911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_fcrb->srej_rcv_hold_q = NULL; 2285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 229911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson fixed_queue_free(p_fcrb->retrans_q, osi_free); 230911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_fcrb->retrans_q = NULL; 2315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ERTM_STATS == TRUE) 233911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((p_ccb->local_cid >= L2CAP_BASE_APPL_CID) && 234911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE)) { 235911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint32_t dur = time_get_os_boottime_ms() - p_ccb->fcrb.connect_tick_count; 236911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson size_t p_str_size = 120; 237911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson char* p_str = (char*)osi_malloc(p_str_size); 238911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t i; 239911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint32_t throughput_avg, ack_delay_avg, ack_q_count_avg; 240911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 241911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson BT_TRACE(TRACE_CTRL_GENERAL | TRACE_LAYER_GKI | TRACE_ORG_GKI, 242911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson TRACE_TYPE_GENERIC, 243911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "--- L2CAP ERTM Stats for CID: 0x%04x Duration: %08ums", 244911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->local_cid, dur); 245911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson BT_TRACE(TRACE_CTRL_GENERAL | TRACE_LAYER_GKI | TRACE_ORG_GKI, 246911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson TRACE_TYPE_GENERIC, 247911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "Retransmissions:%08u Times Flow Controlled:%08u Retrans " 248911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "Touts:%08u Ack Touts:%08u", 249911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.pkts_retransmitted, p_ccb->fcrb.xmit_window_closed, 250911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.retrans_touts, p_ccb->fcrb.xmit_ack_touts); 251911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson BT_TRACE(TRACE_CTRL_GENERAL | TRACE_LAYER_GKI | TRACE_ORG_GKI, 252911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson TRACE_TYPE_GENERIC, 253911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "Times there is less than 2 packets in controller when flow " 254911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "controlled:%08u", 255911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.controller_idle); 256911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson BT_TRACE(TRACE_CTRL_GENERAL | TRACE_LAYER_GKI | TRACE_ORG_GKI, 257911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson TRACE_TYPE_GENERIC, 258911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "max_held_acks:%08u, in_cfg.fcr.tx_win_sz:%08u", 259911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.max_held_acks, p_ccb->peer_cfg.fcr.tx_win_sz); 260911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 261911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson snprintf( 262911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_str, p_str_size, 263911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "Sent Pkts:%08u Bytes:%10u(%06u/sec) RR:%08u REJ:%08u RNR:%08u " 264911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "SREJ:%08u", 265911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.ertm_pkt_counts[0], p_ccb->fcrb.ertm_byte_counts[0], 266911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (dur >= 10 ? (p_ccb->fcrb.ertm_byte_counts[0] * 100) / (dur / 10) : 0), 267911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.s_frames_sent[0], p_ccb->fcrb.s_frames_sent[1], 268911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.s_frames_sent[2], p_ccb->fcrb.s_frames_sent[3]); 269911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 270911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson BT_TRACE(TRACE_CTRL_GENERAL | TRACE_LAYER_GKI | TRACE_ORG_GKI, 271911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson TRACE_TYPE_GENERIC, "%s", p_str); 272911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 273911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson snprintf( 274911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_str, p_str_size, 275911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "Rcvd Pkts:%08u Bytes:%10u(%06u/sec) RR:%08u REJ:%08u RNR:%08u " 276911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "SREJ:%08u", 277911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.ertm_pkt_counts[1], p_ccb->fcrb.ertm_byte_counts[1], 278911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (dur >= 10 ? (p_ccb->fcrb.ertm_byte_counts[1] * 100) / (dur / 10) : 0), 279911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.s_frames_rcvd[0], p_ccb->fcrb.s_frames_rcvd[1], 280911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.s_frames_rcvd[2], p_ccb->fcrb.s_frames_rcvd[3]); 281911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 282911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson BT_TRACE(TRACE_CTRL_GENERAL | TRACE_LAYER_GKI | TRACE_ORG_GKI, 283911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson TRACE_TYPE_GENERIC, "%s", p_str); 284911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 285911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson throughput_avg = 0; 286911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson ack_delay_avg = 0; 287911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson ack_q_count_avg = 0; 288911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 289911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson for (i = 0; i < L2CAP_ERTM_STATS_NUM_AVG; i++) { 290911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (i == p_ccb->fcrb.ack_delay_avg_index) { 291911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson BT_TRACE(TRACE_CTRL_GENERAL | TRACE_LAYER_GKI | TRACE_ORG_GKI, 292911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson TRACE_TYPE_GENERIC, "[%02u] collecting data ...", i); 293911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson continue; 294911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 295911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 296911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson snprintf(p_str, p_str_size, 297911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "[%02u] throughput: %5u, ack_delay avg:%3u, min:%3u, max:%3u, " 298911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "ack_q_count avg:%3u, min:%3u, max:%3u", 299911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson i, p_ccb->fcrb.throughput[i], p_ccb->fcrb.ack_delay_avg[i], 300911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.ack_delay_min[i], p_ccb->fcrb.ack_delay_max[i], 301911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.ack_q_count_avg[i], p_ccb->fcrb.ack_q_count_min[i], 302911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.ack_q_count_max[i]); 303911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 304911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson BT_TRACE(TRACE_CTRL_GENERAL | TRACE_LAYER_GKI | TRACE_ORG_GKI, 305911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson TRACE_TYPE_GENERIC, "%s", p_str); 306911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 307911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson throughput_avg += p_ccb->fcrb.throughput[i]; 308911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson ack_delay_avg += p_ccb->fcrb.ack_delay_avg[i]; 309911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson ack_q_count_avg += p_ccb->fcrb.ack_q_count_avg[i]; 310911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 311911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 312911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson throughput_avg /= (L2CAP_ERTM_STATS_NUM_AVG - 1); 313911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson ack_delay_avg /= (L2CAP_ERTM_STATS_NUM_AVG - 1); 314911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson ack_q_count_avg /= (L2CAP_ERTM_STATS_NUM_AVG - 1); 315911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 316911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson BT_TRACE(TRACE_CTRL_GENERAL | TRACE_LAYER_GKI | TRACE_ORG_GKI, 317911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson TRACE_TYPE_GENERIC, 318911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "throughput_avg: %8u (kbytes/sec), ack_delay_avg: %8u ms, " 319911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "ack_q_count_avg: %8u", 320911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson throughput_avg, ack_delay_avg, ack_q_count_avg); 321911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 322911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson osi_free(p_str); 323911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 324911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson BT_TRACE(TRACE_CTRL_GENERAL | TRACE_LAYER_GKI | TRACE_ORG_GKI, 325911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson TRACE_TYPE_GENERIC, "---"); 326911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 3275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif 3285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 329911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson memset(p_fcrb, 0, sizeof(tL2C_FCRB)); 3305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 3315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 3325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 333ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 334ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2c_fcr_clone_buf 335ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 3369ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Description This function allocates and copies requested part of a 3379ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * buffer at a new-offset. 338ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 339ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns pointer to new buffer 340ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 341ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 342911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsonBT_HDR* l2c_fcr_clone_buf(BT_HDR* p_buf, uint16_t new_offset, 343911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t no_of_bytes) { 344f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(p_buf != NULL); 345911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* 346911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson * NOTE: We allocate extra L2CAP_FCS_LEN octets, in case we need to put 347911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson * the FCS (Frame Check Sequence) at the end of the buffer. 348911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson */ 349911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t buf_size = no_of_bytes + sizeof(BT_HDR) + new_offset + L2CAP_FCS_LEN; 350871e9ba3063530a81ca7ff03e8433c25e1e8c096Pavlin Radoslavov#if (L2CAP_ERTM_STATS == TRUE) 351911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* 352911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson * NOTE: If L2CAP_ERTM_STATS is enabled, we need 4 extra octets at the 353911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson * end for a timestamp at the end of an I-frame. 354911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson */ 355911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson buf_size += sizeof(uint32_t); 356871e9ba3063530a81ca7ff03e8433c25e1e8c096Pavlin Radoslavov#endif 357911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson BT_HDR* p_buf2 = (BT_HDR*)osi_malloc(buf_size); 3585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 359911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf2->offset = new_offset; 360911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf2->len = no_of_bytes; 361911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson memcpy(((uint8_t*)(p_buf2 + 1)) + p_buf2->offset, 362911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson ((uint8_t*)(p_buf + 1)) + p_buf->offset, no_of_bytes); 3635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 364911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (p_buf2); 3655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 3665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 3675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 368ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 369ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2c_fcr_is_flow_controlled 370ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 371ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description This function checks if the CCB is flow controlled by peer. 372ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 373ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns The control word 374ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 375ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 376911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool l2c_fcr_is_flow_controlled(tL2C_CCB* p_ccb) { 377f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(p_ccb != NULL); 378911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) { 379911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Check if remote side flowed us off or the transmit window is full */ 380911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((p_ccb->fcrb.remote_busy == true) || 381911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (fixed_queue_length(p_ccb->fcrb.waiting_for_ack_q) >= 382911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->peer_cfg.fcr.tx_win_sz)) { 3835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ERTM_STATS == TRUE) 384911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (!fixed_queue_is_empty(p_ccb->xmit_hold_q)) { 385911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.xmit_window_closed++; 3865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 387911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((p_ccb->p_lcb->sent_not_acked < 2) && 388911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (l2cb.controller_xmit_window > 0)) 389911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.controller_idle++; 390911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 3915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif 392911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (true); 3935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 394911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 395911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (false); 3965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 3975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 3985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 399ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 400ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function prepare_I_frame 401ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 402ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description This function sets the FCR variables in an I-frame that is 403ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * about to be sent to HCI for transmission. This may be the 404ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * first time the I-frame is sent, or a retransmission 405ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 406ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns - 407ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 408ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 409911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic void prepare_I_frame(tL2C_CCB* p_ccb, BT_HDR* p_buf, 410911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson bool is_retransmission) { 411f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(p_ccb != NULL); 412f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(p_buf != NULL); 413911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tL2C_FCRB* p_fcrb = &p_ccb->fcrb; 414911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t* p; 415911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t fcs; 416911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t ctrl_word; 417911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson bool set_f_bit = p_fcrb->send_f_rsp; 4185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 419911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_fcrb->send_f_rsp = false; 4205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 421911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (is_retransmission) { 422911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Get the old control word and clear out the old req_seq and F bits */ 423911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p = ((uint8_t*)(p_buf + 1)) + p_buf->offset + L2CAP_PKT_OVERHEAD; 4245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 425911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson STREAM_TO_UINT16(ctrl_word, p); 4265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 427911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson ctrl_word &= ~(L2CAP_FCR_REQ_SEQ_BITS + L2CAP_FCR_F_BIT); 428911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 429911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson ctrl_word = p_buf->layer_specific & L2CAP_FCR_SEG_BITS; /* SAR bits */ 430911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson ctrl_word |= 431911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (p_fcrb->next_tx_seq << L2CAP_FCR_TX_SEQ_BITS_SHIFT); /* Tx Seq */ 4325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 433911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_fcrb->next_tx_seq = (p_fcrb->next_tx_seq + 1) & L2CAP_FCR_SEQ_MODULO; 434911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 4355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 436911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Set the F-bit and reqseq only if using re-transmission mode */ 437911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) { 438911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (set_f_bit) ctrl_word |= L2CAP_FCR_F_BIT; 4395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 440911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson ctrl_word |= (p_fcrb->next_seq_expected) << L2CAP_FCR_REQ_SEQ_BITS_SHIFT; 4415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 442911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_fcrb->last_ack_sent = p_ccb->fcrb.next_seq_expected; 4435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 444911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson alarm_cancel(p_ccb->fcrb.ack_timer); 445911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 4465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 447911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Set the control word */ 448911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p = ((uint8_t*)(p_buf + 1)) + p_buf->offset + L2CAP_PKT_OVERHEAD; 4495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 450911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, ctrl_word); 4515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 452911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Compute the FCS and add to the end of the buffer if not bypassed */ 453911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->bypass_fcs != L2CAP_BYPASS_FCS) { 454911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* length field in l2cap header has to include FCS length */ 455911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p = ((uint8_t*)(p_buf + 1)) + p_buf->offset; 456911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, p_buf->len + L2CAP_FCS_LEN - L2CAP_PKT_OVERHEAD); 4575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 458911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Calculate the FCS */ 459911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson fcs = l2c_fcr_tx_get_fcs(p_buf); 4605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 461911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Point to the end of the buffer and put the FCS there */ 462911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* 463911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson * NOTE: Here we assume the allocated buffer is large enough 464911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson * to include extra L2CAP_FCS_LEN octets at the end. 465911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson */ 466911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p = ((uint8_t*)(p_buf + 1)) + p_buf->offset + p_buf->len; 467911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 468911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, fcs); 469911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 470911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf->len += L2CAP_FCS_LEN; 471911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 472911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 473911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (is_retransmission) { 474911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_EVENT( 475911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "L2CAP eRTM ReTx I-frame CID: 0x%04x Len: %u SAR: %s TxSeq: %u " 476911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "ReqSeq: %u F: %u", 477911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->local_cid, p_buf->len, 478911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson SAR_types[(ctrl_word & L2CAP_FCR_SAR_BITS) >> L2CAP_FCR_SAR_BITS_SHIFT], 479911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (ctrl_word & L2CAP_FCR_TX_SEQ_BITS) >> L2CAP_FCR_TX_SEQ_BITS_SHIFT, 480911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (ctrl_word & L2CAP_FCR_REQ_SEQ_BITS) >> L2CAP_FCR_REQ_SEQ_BITS_SHIFT, 481911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (ctrl_word & L2CAP_FCR_F_BIT) >> L2CAP_FCR_F_BIT_SHIFT); 482911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 483911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_EVENT( 484911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "L2CAP eRTM Tx I-frame CID: 0x%04x Len: %u SAR: %-12s TxSeq: %u " 485911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "ReqSeq: %u F: %u", 486911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->local_cid, p_buf->len, 487911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson SAR_types[(ctrl_word & L2CAP_FCR_SAR_BITS) >> L2CAP_FCR_SAR_BITS_SHIFT], 488911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (ctrl_word & L2CAP_FCR_TX_SEQ_BITS) >> L2CAP_FCR_TX_SEQ_BITS_SHIFT, 489911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (ctrl_word & L2CAP_FCR_REQ_SEQ_BITS) >> L2CAP_FCR_REQ_SEQ_BITS_SHIFT, 490911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (ctrl_word & L2CAP_FCR_F_BIT) >> L2CAP_FCR_F_BIT_SHIFT); 491911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 492911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 493911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Start the retransmission timer if not already running */ 494911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) 495911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_fcr_start_timer(p_ccb); 4965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 4975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 4985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 499ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 500ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2c_fcr_send_S_frame 501ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 502ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description This function formats and sends an S-frame for transmission. 503ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 504ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns - 505ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 506ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 507911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2c_fcr_send_S_frame(tL2C_CCB* p_ccb, uint16_t function_code, 508911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t pf_bit) { 509f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(p_ccb != NULL); 510911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t* p; 511911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t ctrl_word; 512911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t fcs; 5135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 514911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((!p_ccb->in_use) || (p_ccb->chnl_state != CST_OPEN)) return; 5155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 5165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ERTM_STATS == TRUE) 517911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.s_frames_sent[function_code]++; 5185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif 5195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 520911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (pf_bit == L2CAP_FCR_P_BIT) { 521911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.wait_ack = true; 522911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 523911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_fcr_stop_timer(p_ccb); /* Restart the monitor timer */ 524911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_fcr_start_timer(p_ccb); 525911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 526911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 527911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Create the control word to use */ 528911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson ctrl_word = (function_code << L2CAP_FCR_SUP_SHIFT) | L2CAP_FCR_S_FRAME_BIT; 529911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson ctrl_word |= (p_ccb->fcrb.next_seq_expected << L2CAP_FCR_REQ_SEQ_BITS_SHIFT); 530911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson ctrl_word |= pf_bit; 531911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 532911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson BT_HDR* p_buf = (BT_HDR*)osi_malloc(L2CAP_CMD_BUF_SIZE); 533911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf->offset = HCI_DATA_PREAMBLE_SIZE; 534911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf->len = L2CAP_PKT_OVERHEAD + L2CAP_FCR_OVERHEAD; 535911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 536911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Set the pointer to the beginning of the data */ 537911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p = (uint8_t*)(p_buf + 1) + p_buf->offset; 538911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 539911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Put in the L2CAP header */ 540911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, L2CAP_FCR_OVERHEAD + L2CAP_FCS_LEN); 541911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, p_ccb->remote_cid); 542911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, ctrl_word); 543911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 544911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Compute the FCS and add to the end of the buffer if not bypassed */ 545911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->bypass_fcs != L2CAP_BYPASS_FCS) { 546911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson fcs = l2c_fcr_tx_get_fcs(p_buf); 547911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 548911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, fcs); 549911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf->len += L2CAP_FCS_LEN; 550911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 551911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* rewrite the length without FCS length */ 552911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p -= 6; 553911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, L2CAP_FCR_OVERHEAD); 554911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 555911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 556911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Now, the HCI transport header */ 557911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf->layer_specific = L2CAP_NON_FLUSHABLE_PKT; 558911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cu_set_acl_hci_header(p_buf, p_ccb); 559911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 560911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((((ctrl_word & L2CAP_FCR_SUP_BITS) >> L2CAP_FCR_SUP_SHIFT) == 1) || 561911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (((ctrl_word & L2CAP_FCR_SUP_BITS) >> L2CAP_FCR_SUP_SHIFT) == 3)) { 562911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_WARNING( 563911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "L2CAP eRTM Tx S-frame CID: 0x%04x ctrlword: 0x%04x Type: %s " 564911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "ReqSeq: %u P: %u F: %u", 565911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->local_cid, ctrl_word, 566911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson SUP_types[(ctrl_word & L2CAP_FCR_SUP_BITS) >> L2CAP_FCR_SUP_SHIFT], 567911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (ctrl_word & L2CAP_FCR_REQ_SEQ_BITS) >> L2CAP_FCR_REQ_SEQ_BITS_SHIFT, 568911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (ctrl_word & L2CAP_FCR_P_BIT) >> L2CAP_FCR_P_BIT_SHIFT, 569911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (ctrl_word & L2CAP_FCR_F_BIT) >> L2CAP_FCR_F_BIT_SHIFT); 570911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_WARNING(" Buf Len: %u", p_buf->len); 571911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 572911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_EVENT( 573911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "L2CAP eRTM Tx S-frame CID: 0x%04x ctrlword: 0x%04x Type: %s " 574911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "ReqSeq: %u P: %u F: %u", 575911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->local_cid, ctrl_word, 576911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson SUP_types[(ctrl_word & L2CAP_FCR_SUP_BITS) >> L2CAP_FCR_SUP_SHIFT], 577911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (ctrl_word & L2CAP_FCR_REQ_SEQ_BITS) >> L2CAP_FCR_REQ_SEQ_BITS_SHIFT, 578911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (ctrl_word & L2CAP_FCR_P_BIT) >> L2CAP_FCR_P_BIT_SHIFT, 579911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (ctrl_word & L2CAP_FCR_F_BIT) >> L2CAP_FCR_F_BIT_SHIFT); 580911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_EVENT(" Buf Len: %u", p_buf->len); 581911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 582911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 583911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_link_check_send_pkts(p_ccb->p_lcb, NULL, p_buf); 584911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 585911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.last_ack_sent = p_ccb->fcrb.next_seq_expected; 586911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 587911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson alarm_cancel(p_ccb->fcrb.ack_timer); 5885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 5895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 5905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 591ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 592ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2c_fcr_proc_pdu 593ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 594ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description This function is the entry point for processing of a 5959ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * received PDU when in flow control and/or retransmission 5969ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * modes. 597ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 598ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns - 599ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 600ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 601911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2c_fcr_proc_pdu(tL2C_CCB* p_ccb, BT_HDR* p_buf) { 602f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(p_ccb != NULL); 603f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(p_buf != NULL); 604911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t* p; 605911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t fcs; 606911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t min_pdu_len; 607911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t ctrl_word; 608911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 609911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Check the length */ 610911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson min_pdu_len = (p_ccb->bypass_fcs == L2CAP_BYPASS_FCS) 611911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson ? (uint16_t)L2CAP_FCR_OVERHEAD 612911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson : (uint16_t)(L2CAP_FCS_LEN + L2CAP_FCR_OVERHEAD); 613911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 614911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_buf->len < min_pdu_len) { 615911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_WARNING("Rx L2CAP PDU: CID: 0x%04x Len too short: %u", 616911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->local_cid, p_buf->len); 617911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson osi_free(p_buf); 618911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return; 619911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 6205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 621911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_STREAM_MODE) { 622911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson process_stream_frame(p_ccb, p_buf); 623911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return; 624911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 625911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 626911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Get the control word */ 627911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p = ((uint8_t*)(p_buf + 1)) + p_buf->offset; 628911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson STREAM_TO_UINT16(ctrl_word, p); 629911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 630911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (ctrl_word & L2CAP_FCR_S_FRAME_BIT) { 631911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((((ctrl_word & L2CAP_FCR_SUP_BITS) >> L2CAP_FCR_SUP_SHIFT) == 1) || 632911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (((ctrl_word & L2CAP_FCR_SUP_BITS) >> L2CAP_FCR_SUP_SHIFT) == 3)) { 633911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* REJ or SREJ */ 634911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_WARNING( 635911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "L2CAP eRTM Rx S-frame: cid: 0x%04x Len: %u Type: %s ReqSeq: %u " 636911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "P: %u F: %u", 637911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->local_cid, p_buf->len, 638911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson SUP_types[(ctrl_word & L2CAP_FCR_SUP_BITS) >> L2CAP_FCR_SUP_SHIFT], 639911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (ctrl_word & L2CAP_FCR_REQ_SEQ_BITS) >> L2CAP_FCR_REQ_SEQ_BITS_SHIFT, 640911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (ctrl_word & L2CAP_FCR_P_BIT) >> L2CAP_FCR_P_BIT_SHIFT, 641911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (ctrl_word & L2CAP_FCR_F_BIT) >> L2CAP_FCR_F_BIT_SHIFT); 642911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 643911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_EVENT( 644911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "L2CAP eRTM Rx S-frame: cid: 0x%04x Len: %u Type: %s ReqSeq: %u " 645911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "P: %u F: %u", 646911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->local_cid, p_buf->len, 647911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson SUP_types[(ctrl_word & L2CAP_FCR_SUP_BITS) >> L2CAP_FCR_SUP_SHIFT], 648911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (ctrl_word & L2CAP_FCR_REQ_SEQ_BITS) >> L2CAP_FCR_REQ_SEQ_BITS_SHIFT, 649911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (ctrl_word & L2CAP_FCR_P_BIT) >> L2CAP_FCR_P_BIT_SHIFT, 650911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (ctrl_word & L2CAP_FCR_F_BIT) >> L2CAP_FCR_F_BIT_SHIFT); 651911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 652911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 653911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_EVENT( 654911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "L2CAP eRTM Rx I-frame: cid: 0x%04x Len: %u SAR: %-12s TxSeq: %u " 655911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "ReqSeq: %u F: %u", 656911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->local_cid, p_buf->len, 657911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson SAR_types[(ctrl_word & L2CAP_FCR_SAR_BITS) >> L2CAP_FCR_SAR_BITS_SHIFT], 658911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (ctrl_word & L2CAP_FCR_TX_SEQ_BITS) >> L2CAP_FCR_TX_SEQ_BITS_SHIFT, 659911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (ctrl_word & L2CAP_FCR_REQ_SEQ_BITS) >> L2CAP_FCR_REQ_SEQ_BITS_SHIFT, 660911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (ctrl_word & L2CAP_FCR_F_BIT) >> L2CAP_FCR_F_BIT_SHIFT); 661911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 662911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 663911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_EVENT( 664911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson " eRTM Rx Nxt_tx_seq %u, Lst_rx_ack %u, Nxt_seq_exp %u, Lst_ack_snt " 665911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "%u, wt_q.cnt %u, tries %u", 666911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.next_tx_seq, p_ccb->fcrb.last_rx_ack, 667911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.next_seq_expected, p_ccb->fcrb.last_ack_sent, 668911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson fixed_queue_length(p_ccb->fcrb.waiting_for_ack_q), p_ccb->fcrb.num_tries); 669911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 670911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Verify FCS if using */ 671911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->bypass_fcs != L2CAP_BYPASS_FCS) { 672911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p = ((uint8_t*)(p_buf + 1)) + p_buf->offset + p_buf->len - L2CAP_FCS_LEN; 673911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 674911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Extract and drop the FCS from the packet */ 675911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson STREAM_TO_UINT16(fcs, p); 676911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf->len -= L2CAP_FCS_LEN; 677911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 678911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (l2c_fcr_rx_get_fcs(p_buf) != fcs) { 679911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_WARNING("Rx L2CAP PDU: CID: 0x%04x BAD FCS", 680911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->local_cid); 681911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson osi_free(p_buf); 682911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return; 683911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 684911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 685911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 686911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Get the control word */ 687911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p = ((uint8_t*)(p_buf + 1)) + p_buf->offset; 688911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 689911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson STREAM_TO_UINT16(ctrl_word, p); 690911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 691911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf->len -= L2CAP_FCR_OVERHEAD; 692911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf->offset += L2CAP_FCR_OVERHEAD; 693911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 694911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If we had a poll bit outstanding, check if we got a final response */ 695911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->fcrb.wait_ack) { 696911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If final bit not set, ignore the frame unless it is a polled S-frame */ 697911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (!(ctrl_word & L2CAP_FCR_F_BIT)) { 698911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((ctrl_word & L2CAP_FCR_P_BIT) && 699911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (ctrl_word & L2CAP_FCR_S_FRAME_BIT)) { 700911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->fcrb.srej_sent) 701911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_fcr_send_S_frame(p_ccb, L2CAP_FCR_SUP_SREJ, L2CAP_FCR_F_BIT); 702911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson else if (p_ccb->fcrb.local_busy) 703911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_fcr_send_S_frame(p_ccb, L2CAP_FCR_SUP_RNR, L2CAP_FCR_F_BIT); 7045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project else 705911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_fcr_send_S_frame(p_ccb, L2CAP_FCR_SUP_RR, L2CAP_FCR_F_BIT); 706911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 707911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Got a poll while in wait_ack state, so re-start our timer with 708911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson * 1-second */ 709911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* This is a small optimization... the monitor timer is 12 secs, but we 710911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson * saw */ 711911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* that if the other side sends us a poll when we are waiting for a 712911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson * final, */ 713911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* then it speeds up recovery significantly if we poll him back soon 714911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson * after his poll. */ 715911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson alarm_set_on_queue(p_ccb->fcrb.mon_retrans_timer, BT_1SEC_TIMEOUT_MS, 716911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_ccb_timer_timeout, p_ccb, 717911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson btu_general_alarm_queue); 718911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 719911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson osi_free(p_buf); 720911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return; 7215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 7225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 723911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.wait_ack = false; 7245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 725911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* P and F are mutually exclusive */ 726911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (ctrl_word & L2CAP_FCR_S_FRAME_BIT) ctrl_word &= ~L2CAP_FCR_P_BIT; 7275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 728911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (fixed_queue_is_empty(p_ccb->fcrb.waiting_for_ack_q)) 729911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.num_tries = 0; 7305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 731911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_fcr_stop_timer(p_ccb); 732911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 733911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Otherwise, ensure the final bit is ignored */ 734911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson ctrl_word &= ~L2CAP_FCR_F_BIT; 735911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 7365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 737911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Process receive sequence number */ 738911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (!process_reqseq(p_ccb, ctrl_word)) { 739911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson osi_free(p_buf); 740911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return; 741911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 742911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 743911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Process based on whether it is an S-frame or an I-frame */ 744911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (ctrl_word & L2CAP_FCR_S_FRAME_BIT) 745911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson process_s_frame(p_ccb, p_buf, ctrl_word); 746911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson else 747911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson process_i_frame(p_ccb, p_buf, ctrl_word, false); 748911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 749911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Return if the channel got disconnected by a bad packet or max 750911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson * retransmissions */ 751911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((!p_ccb->in_use) || (p_ccb->chnl_state != CST_OPEN)) return; 752911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 753911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If we have some buffers held while doing SREJ, and SREJ has cleared, 754911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson * process them now */ 755911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((!p_ccb->fcrb.local_busy) && (!p_ccb->fcrb.srej_sent) && 756911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (!fixed_queue_is_empty(p_ccb->fcrb.srej_rcv_hold_q))) { 757911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson fixed_queue_t* temp_q = p_ccb->fcrb.srej_rcv_hold_q; 758911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.srej_rcv_hold_q = fixed_queue_new(SIZE_MAX); 759911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 760911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson while ((p_buf = (BT_HDR*)fixed_queue_try_dequeue(temp_q)) != NULL) { 761911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->in_use && (p_ccb->chnl_state == CST_OPEN)) { 762911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Get the control word */ 763911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p = ((uint8_t*)(p_buf + 1)) + p_buf->offset - L2CAP_FCR_OVERHEAD; 764911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 765911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson STREAM_TO_UINT16(ctrl_word, p); 766911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 767911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_DEBUG( 768911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "l2c_fcr_proc_pdu() CID: 0x%04x Process Buffer from SREJ_Hold_Q " 769911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "TxSeq: %u Expected_Seq: %u", 770911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->local_cid, 771911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (ctrl_word & L2CAP_FCR_TX_SEQ_BITS) >> L2CAP_FCR_TX_SEQ_BITS_SHIFT, 772911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.next_seq_expected); 773911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 774911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Process the SREJ held I-frame, but do not send an RR for each 775911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson * individual frame */ 776911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson process_i_frame(p_ccb, p_buf, ctrl_word, true); 777911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else 778cceb430489a70add1b996d54289867c17f4ac0fdPavlin Radoslavov osi_free(p_buf); 7795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 780911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If more frames were lost during SREJ, send a REJ */ 781911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->fcrb.rej_after_srej) { 782911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.rej_after_srej = false; 783911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.rej_sent = true; 784911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 785911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_fcr_send_S_frame(p_ccb, L2CAP_FCR_SUP_REJ, 0); 786911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 787911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 788911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson fixed_queue_free(temp_q, NULL); 789911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 790911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Now, if needed, send one RR for the whole held queue */ 791911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((!p_ccb->fcrb.local_busy) && (!p_ccb->fcrb.rej_sent) && 792911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (!p_ccb->fcrb.srej_sent) && 793911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (p_ccb->fcrb.next_seq_expected != p_ccb->fcrb.last_ack_sent)) 794911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_fcr_send_S_frame(p_ccb, L2CAP_FCR_SUP_RR, 0); 795911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson else { 796911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_DEBUG( 797911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "l2c_fcr_proc_pdu() not sending RR CID: 0x%04x local_busy:%d " 798911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "rej_sent:%d srej_sent:%d Expected_Seq:%u Last_Ack:%u", 799911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->local_cid, p_ccb->fcrb.local_busy, p_ccb->fcrb.rej_sent, 800911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.srej_sent, p_ccb->fcrb.next_seq_expected, 801911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.last_ack_sent); 802911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 803911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 804911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 805911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If a window has opened, check if we can send any more packets */ 806911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((!fixed_queue_is_empty(p_ccb->fcrb.retrans_q) || 807911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson !fixed_queue_is_empty(p_ccb->xmit_hold_q)) && 808911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (p_ccb->fcrb.wait_ack == false) && 809911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (l2c_fcr_is_flow_controlled(p_ccb) == false)) { 810911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_link_check_send_pkts(p_ccb->p_lcb, NULL, NULL); 811911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 8125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 8135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 8145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 815ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 816ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2c_lcc_proc_pdu 817ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 818ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description This function is the entry point for processing of a 819ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * received PDU when in LE Coc flow control modes. 820ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 821ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns - 822ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 823ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 824911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2c_lcc_proc_pdu(tL2C_CCB* p_ccb, BT_HDR* p_buf) { 825f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(p_ccb != NULL); 826f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(p_buf != NULL); 827911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t* p = (uint8_t*)(p_buf + 1) + p_buf->offset; 828911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t sdu_length; 829911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson BT_HDR* p_data = NULL; 830911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 831911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Buffer length should not exceed local mps */ 832911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_buf->len > p_ccb->local_conn_cfg.mps) { 833911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Discard the buffer */ 8346721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar osi_free(p_buf); 8356721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar return; 836911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 837911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 838911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->is_first_seg) { 839911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson STREAM_TO_UINT16(sdu_length, p); 840911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Check the SDU Length with local MTU size */ 841911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (sdu_length > p_ccb->local_conn_cfg.mtu) { 842911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Discard the buffer */ 843911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson osi_free(p_buf); 844911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return; 845911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 846911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 847911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_data = (BT_HDR*)osi_malloc(L2CAP_MAX_BUF_SIZE); 848911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_data == NULL) { 849911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson osi_free(p_buf); 850911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return; 851911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 852911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 853911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->ble_sdu = p_data; 854911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_data->len = 0; 855911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->ble_sdu_length = sdu_length; 856911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_DEBUG("%s SDU Length = %d", __func__, sdu_length); 857911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf->len -= sizeof(sdu_length); 858911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf->offset += sizeof(sdu_length); 859911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_data->offset = 0; 860911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 861911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else 862911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_data = p_ccb->ble_sdu; 863911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 864911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson memcpy((uint8_t*)(p_data + 1) + p_data->offset + p_data->len, 865911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (uint8_t*)(p_buf + 1) + p_buf->offset, p_buf->len); 866911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_data->len += p_buf->len; 867911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p = (uint8_t*)(p_data + 1) + p_data->offset; 868911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_data->len == p_ccb->ble_sdu_length) { 869911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_csm_execute(p_ccb, L2CEVT_L2CAP_DATA, p_data); 870911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->is_first_seg = true; 871911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->ble_sdu = NULL; 872911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->ble_sdu_length = 0; 873911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else if (p_data->len < p_ccb->ble_sdu_length) { 874911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->is_first_seg = false; 875911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 876911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_ERROR("%s Length in the SDU messed up", __func__); 877911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson // TODO: reset every thing may be??? 878911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 879911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 880911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson osi_free(p_buf); 881911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return; 8826721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar} 8836721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 8846721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar/******************************************************************************* 885ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 886ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2c_fcr_proc_tout 887ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 888ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Handle a timeout. We should be in error recovery state. 889ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 890ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns - 891ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 892ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 893911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2c_fcr_proc_tout(tL2C_CCB* p_ccb) { 894f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(p_ccb != NULL); 895911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_DEBUG( 896911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "l2c_fcr_proc_tout: CID: 0x%04x num_tries: %u (max: %u) wait_ack: %u " 897911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "ack_q_count: %u", 898911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->local_cid, p_ccb->fcrb.num_tries, p_ccb->peer_cfg.fcr.max_transmit, 899911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.wait_ack, fixed_queue_length(p_ccb->fcrb.waiting_for_ack_q)); 9005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 9015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ERTM_STATS == TRUE) 902911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.retrans_touts++; 9035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif 9045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 905911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((p_ccb->peer_cfg.fcr.max_transmit != 0) && 906911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (++p_ccb->fcrb.num_tries > p_ccb->peer_cfg.fcr.max_transmit)) { 907911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cu_disconnect_chnl(p_ccb); 908911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 909911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (!p_ccb->fcrb.srej_sent && !p_ccb->fcrb.rej_sent) { 910911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->fcrb.local_busy) 911911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_fcr_send_S_frame(p_ccb, L2CAP_FCR_SUP_RNR, L2CAP_FCR_P_BIT); 912911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson else 913911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_fcr_send_S_frame(p_ccb, L2CAP_FCR_SUP_RR, L2CAP_FCR_P_BIT); 914911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 915911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 9165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 9175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 9185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 919ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 920ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2c_fcr_proc_ack_tout 921ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 922ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Send RR/RNR if we have not acked I frame 923ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 924ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns - 925ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 926ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 927911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2c_fcr_proc_ack_tout(tL2C_CCB* p_ccb) { 928f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(p_ccb != NULL); 929911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_DEBUG( 930911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "l2c_fcr_proc_ack_tout: CID: 0x%04x State: %u Wack:%u Rq:%d Acked:%d", 931911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->local_cid, p_ccb->chnl_state, p_ccb->fcrb.wait_ack, 932911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.next_seq_expected, p_ccb->fcrb.last_ack_sent); 933911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 934911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((p_ccb->chnl_state == CST_OPEN) && (!p_ccb->fcrb.wait_ack) && 935911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (p_ccb->fcrb.last_ack_sent != p_ccb->fcrb.next_seq_expected)) { 9365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ERTM_STATS == TRUE) 937911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.xmit_ack_touts++; 9385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif 939911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->fcrb.local_busy) 940911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_fcr_send_S_frame(p_ccb, L2CAP_FCR_SUP_RNR, 0); 941911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson else 942911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_fcr_send_S_frame(p_ccb, L2CAP_FCR_SUP_RR, 0); 943911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 9445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 9455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 9465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 947ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 948ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function process_reqseq 949ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 950ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Handle receive sequence number 951ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 952ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns - 953ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 954ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 955911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic bool process_reqseq(tL2C_CCB* p_ccb, uint16_t ctrl_word) { 956f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(p_ccb != NULL); 957911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tL2C_FCRB* p_fcrb = &p_ccb->fcrb; 958911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t req_seq, num_bufs_acked, xx; 959911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t ls; 960911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t full_sdus_xmitted; 961911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 962911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Receive sequence number does not ack anything for SREJ with P-bit set to 963911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson * zero */ 964911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((ctrl_word & L2CAP_FCR_S_FRAME_BIT) && 965911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson ((ctrl_word & L2CAP_FCR_SUP_BITS) == 966911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (L2CAP_FCR_SUP_SREJ << L2CAP_FCR_SUP_SHIFT)) && 967911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson ((ctrl_word & L2CAP_FCR_P_BIT) == 0)) { 968911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If anything still waiting for ack, restart the timer if it was stopped */ 969911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (!fixed_queue_is_empty(p_fcrb->waiting_for_ack_q)) 970911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_fcr_start_timer(p_ccb); 9715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 972911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (true); 973911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 9745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 975911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Extract the receive sequence number from the control word */ 976911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson req_seq = 977911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (ctrl_word & L2CAP_FCR_REQ_SEQ_BITS) >> L2CAP_FCR_REQ_SEQ_BITS_SHIFT; 9785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 979911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson num_bufs_acked = (req_seq - p_fcrb->last_rx_ack) & L2CAP_FCR_SEQ_MODULO; 9805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 981911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Verify the request sequence is in range before proceeding */ 982911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (num_bufs_acked > fixed_queue_length(p_fcrb->waiting_for_ack_q)) { 983911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* The channel is closed if ReqSeq is not in range */ 984911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_WARNING( 985911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "L2CAP eRTM Frame BAD Req_Seq - ctrl_word: 0x%04x req_seq 0x%02x " 986911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "last_rx_ack: 0x%02x QCount: %u", 987911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson ctrl_word, req_seq, p_fcrb->last_rx_ack, 988911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson fixed_queue_length(p_fcrb->waiting_for_ack_q)); 9895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 990911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cu_disconnect_chnl(p_ccb); 991911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (false); 992911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 9935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 994911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_fcrb->last_rx_ack = req_seq; 9955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 996911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Now we can release all acknowledged frames, and restart the retransmission 997911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson * timer if needed */ 998911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (num_bufs_acked != 0) { 999911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_fcrb->num_tries = 0; 1000911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson full_sdus_xmitted = 0; 10015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 10025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ERTM_STATS == TRUE) 1003911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_fcr_collect_ack_delay(p_ccb, num_bufs_acked); 10045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif 10055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1006911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson for (xx = 0; xx < num_bufs_acked; xx++) { 1007911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson BT_HDR* p_tmp = 1008911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (BT_HDR*)fixed_queue_try_dequeue(p_fcrb->waiting_for_ack_q); 1009911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson ls = p_tmp->layer_specific & L2CAP_FCR_SAR_BITS; 10105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1011911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((ls == L2CAP_FCR_UNSEG_SDU) || (ls == L2CAP_FCR_END_SDU)) 1012911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson full_sdus_xmitted++; 10135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1014911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson osi_free(p_tmp); 1015911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 10165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1017911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If we are still in a wait_ack state, do not mess with the timer */ 1018911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (!p_ccb->fcrb.wait_ack) l2c_fcr_stop_timer(p_ccb); 10195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1020911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Check if we need to call the "packet_sent" callback */ 1021911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((p_ccb->p_rcb) && (p_ccb->p_rcb->api.pL2CA_TxComplete_Cb) && 1022911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (full_sdus_xmitted)) { 1023911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Special case for eRTM, if all packets sent, send 0xFFFF */ 1024911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (fixed_queue_is_empty(p_fcrb->waiting_for_ack_q) && 1025911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson fixed_queue_is_empty(p_ccb->xmit_hold_q)) { 1026911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson full_sdus_xmitted = 0xFFFF; 1027911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1028911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1029911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (*p_ccb->p_rcb->api.pL2CA_TxComplete_Cb)(p_ccb->local_cid, 1030911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson full_sdus_xmitted); 10315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 1032911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 10335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1034911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If anything still waiting for ack, restart the timer if it was stopped */ 1035911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (!fixed_queue_is_empty(p_fcrb->waiting_for_ack_q)) 1036911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_fcr_start_timer(p_ccb); 1037911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (true); 10385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 10395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 10405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 1041ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1042ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function process_s_frame 1043ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1044ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Process an S frame 1045ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1046ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns - 1047ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1048ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 1049911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic void process_s_frame(tL2C_CCB* p_ccb, BT_HDR* p_buf, 1050911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t ctrl_word) { 1051f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(p_ccb != NULL); 1052f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(p_buf != NULL); 1053ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton 1054911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tL2C_FCRB* p_fcrb = &p_ccb->fcrb; 1055911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t s_frame_type = 1056911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (ctrl_word & L2CAP_FCR_SUP_BITS) >> L2CAP_FCR_SUP_SHIFT; 1057911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson bool remote_was_busy; 1058911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson bool all_ok = true; 10595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1060911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_buf->len != 0) { 1061911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_WARNING("Incorrect S-frame Length (%d)", p_buf->len); 1062911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 10635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1064911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_DEBUG("process_s_frame ctrl_word 0x%04x fcrb_remote_busy:%d", 1065911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson ctrl_word, p_fcrb->remote_busy); 10665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 10675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ERTM_STATS == TRUE) 1068911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.s_frames_rcvd[s_frame_type]++; 10695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif 10705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1071911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (ctrl_word & L2CAP_FCR_P_BIT) { 1072911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_fcrb->rej_sent = false; /* After checkpoint, we can send anoher REJ */ 1073911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_fcrb->send_f_rsp = true; /* Set a flag in case an I-frame is pending */ 1074911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 10755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1076911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson switch (s_frame_type) { 10775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project case L2CAP_FCR_SUP_RR: 1078911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson remote_was_busy = p_fcrb->remote_busy; 1079911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_fcrb->remote_busy = false; 10805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1081911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((ctrl_word & L2CAP_FCR_F_BIT) || (remote_was_busy)) 1082911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson all_ok = retransmit_i_frames(p_ccb, L2C_FCR_RETX_ALL_PKTS); 1083911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson break; 10845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 10855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project case L2CAP_FCR_SUP_REJ: 1086911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_fcrb->remote_busy = false; 1087911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson all_ok = retransmit_i_frames(p_ccb, L2C_FCR_RETX_ALL_PKTS); 1088911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson break; 10895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 10905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project case L2CAP_FCR_SUP_RNR: 1091911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_fcrb->remote_busy = true; 1092911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_fcr_stop_timer(p_ccb); 1093911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson break; 10945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 10955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project case L2CAP_FCR_SUP_SREJ: 1096911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_fcrb->remote_busy = false; 1097911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson all_ok = retransmit_i_frames( 1098911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb, (uint8_t)((ctrl_word & L2CAP_FCR_REQ_SEQ_BITS) >> 1099911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_FCR_REQ_SEQ_BITS_SHIFT)); 1100911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson break; 1101911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1102911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1103911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (all_ok) { 1104911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If polled, we need to respond with F-bit. Note, we may have sent a 1105911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson * I-frame with the F-bit */ 1106911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_fcrb->send_f_rsp) { 1107911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_fcrb->srej_sent) 1108911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_fcr_send_S_frame(p_ccb, L2CAP_FCR_SUP_SREJ, L2CAP_FCR_F_BIT); 1109911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson else if (p_fcrb->local_busy) 1110911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_fcr_send_S_frame(p_ccb, L2CAP_FCR_SUP_RNR, L2CAP_FCR_F_BIT); 1111911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson else 1112911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_fcr_send_S_frame(p_ccb, L2CAP_FCR_SUP_RR, L2CAP_FCR_F_BIT); 1113911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1114911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_fcrb->send_f_rsp = false; 1115911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1116911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 1117911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_DEBUG("process_s_frame hit_max_retries"); 1118911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1119911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1120911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson osi_free(p_buf); 11215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 11225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 11235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 1124ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1125ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function process_i_frame 1126ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1127ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Process an I frame 1128ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1129ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns - 1130ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1131ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 1132911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic void process_i_frame(tL2C_CCB* p_ccb, BT_HDR* p_buf, uint16_t ctrl_word, 1133911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson bool delay_ack) { 1134f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(p_ccb != NULL); 1135f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(p_buf != NULL); 1136ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton 1137911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tL2C_FCRB* p_fcrb = &p_ccb->fcrb; 1138911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t tx_seq, num_lost, num_to_ack, next_srej; 11395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1140911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If we were doing checkpoint recovery, first retransmit all unacked I-frames 1141911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson */ 1142911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (ctrl_word & L2CAP_FCR_F_BIT) { 1143911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (!retransmit_i_frames(p_ccb, L2C_FCR_RETX_ALL_PKTS)) { 1144911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson osi_free(p_buf); 1145911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return; 11465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 1147911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 11485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 11495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ERTM_STATS == TRUE) 1150911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.ertm_pkt_counts[1]++; 1151911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.ertm_byte_counts[1] += p_buf->len; 11525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif 11535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1154911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Extract the sequence number */ 1155911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tx_seq = (ctrl_word & L2CAP_FCR_TX_SEQ_BITS) >> L2CAP_FCR_TX_SEQ_BITS_SHIFT; 11565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1157911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If we have flow controlled the peer, ignore any bad I-frames from him */ 1158911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((tx_seq != p_fcrb->next_seq_expected) && (p_fcrb->local_busy)) { 1159911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_WARNING("Dropping bad I-Frame since we flowed off, tx_seq:%u", 1160911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tx_seq); 1161911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_fcr_send_S_frame(p_ccb, L2CAP_FCR_SUP_RNR, 0); 1162911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson osi_free(p_buf); 1163911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return; 1164911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1165911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1166911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Check if tx-sequence is the expected one */ 1167911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (tx_seq != p_fcrb->next_seq_expected) { 1168911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson num_lost = (tx_seq - p_fcrb->next_seq_expected) & L2CAP_FCR_SEQ_MODULO; 1169911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1170911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Is the frame a duplicate ? If so, just drop it */ 1171911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (num_lost >= p_ccb->our_cfg.fcr.tx_win_sz) { 1172911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Duplicate - simply drop it */ 1173911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_WARNING( 1174911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "process_i_frame() Dropping Duplicate Frame tx_seq:%u ExpectedTxSeq " 1175911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "%u", 1176911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tx_seq, p_fcrb->next_seq_expected); 1177911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson osi_free(p_buf); 1178911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 1179911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_WARNING( 1180911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "process_i_frame() CID: 0x%04x Lost: %u tx_seq:%u ExpTxSeq %u " 1181911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "Rej: %u SRej: %u", 1182911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->local_cid, num_lost, tx_seq, p_fcrb->next_seq_expected, 1183911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_fcrb->rej_sent, p_fcrb->srej_sent); 1184911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1185911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_fcrb->srej_sent) { 1186911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If SREJ sent, save the frame for later processing as long as it is in 1187911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson * sequence */ 1188911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson next_srej = 1189911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (((BT_HDR*)fixed_queue_try_peek_last(p_fcrb->srej_rcv_hold_q)) 1190911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson ->layer_specific + 1191911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1) & 1192911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_FCR_SEQ_MODULO; 1193911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1194911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((tx_seq == next_srej) && 1195911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (fixed_queue_length(p_fcrb->srej_rcv_hold_q) < 1196911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->our_cfg.fcr.tx_win_sz)) { 1197911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If user gave us a pool for held rx buffers, use that */ 1198911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* TODO: Could that happen? Get rid of this code. */ 1199911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->ertm_info.fcr_rx_buf_size != L2CAP_FCR_RX_BUF_SIZE) { 1200911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson BT_HDR* p_buf2; 1201911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1202911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Adjust offset and len so that control word is copied */ 1203911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf->offset -= L2CAP_FCR_OVERHEAD; 1204911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf->len += L2CAP_FCR_OVERHEAD; 1205911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1206911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf2 = l2c_fcr_clone_buf(p_buf, p_buf->offset, p_buf->len); 1207911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1208911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_buf2) { 1209911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson osi_free(p_buf); 1210911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf = p_buf2; 12115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 1212911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf->offset += L2CAP_FCR_OVERHEAD; 1213911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf->len -= L2CAP_FCR_OVERHEAD; 1214911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1215911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_DEBUG( 1216911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "process_i_frame() Lost: %u tx_seq:%u ExpTxSeq %u Rej: %u " 1217911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "SRej1", 1218911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson num_lost, tx_seq, p_fcrb->next_seq_expected, p_fcrb->rej_sent); 1219911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1220911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf->layer_specific = tx_seq; 1221911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson fixed_queue_enqueue(p_fcrb->srej_rcv_hold_q, p_buf); 1222911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 1223911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_WARNING( 1224911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "process_i_frame() CID: 0x%04x frame dropped in Srej Sent " 1225911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "next_srej:%u hold_q.count:%u win_sz:%u", 1226911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->local_cid, next_srej, 1227911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson fixed_queue_length(p_fcrb->srej_rcv_hold_q), 1228911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->our_cfg.fcr.tx_win_sz); 1229911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1230911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_fcrb->rej_after_srej = true; 1231911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson osi_free(p_buf); 12325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 1233911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else if (p_fcrb->rej_sent) { 1234911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_WARNING( 1235911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "process_i_frame() CID: 0x%04x Lost: %u tx_seq:%u ExpTxSeq %u " 1236911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "Rej: 1 SRej: %u", 1237911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->local_cid, num_lost, tx_seq, p_fcrb->next_seq_expected, 1238911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_fcrb->srej_sent); 1239911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1240911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If REJ sent, just drop the frame */ 1241911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson osi_free(p_buf); 1242911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 1243911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_DEBUG( 1244911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "process_i_frame() CID: 0x%04x tx_seq:%u ExpTxSeq %u Rej: %u", 1245911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->local_cid, tx_seq, p_fcrb->next_seq_expected, 1246911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_fcrb->rej_sent); 1247911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1248911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If only one lost, we will send SREJ, otherwise we will send REJ */ 1249911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (num_lost > 1) { 1250911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson osi_free(p_buf); 1251911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_fcrb->rej_sent = true; 1252911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_fcr_send_S_frame(p_ccb, L2CAP_FCR_SUP_REJ, 0); 1253911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 1254911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (!fixed_queue_is_empty(p_fcrb->srej_rcv_hold_q)) { 1255911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_ERROR( 1256911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "process_i_frame() CID: 0x%04x sending SREJ tx_seq:%d " 1257911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "hold_q.count:%u", 1258911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->local_cid, tx_seq, 1259911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson fixed_queue_length(p_fcrb->srej_rcv_hold_q)); 1260911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1261911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf->layer_specific = tx_seq; 1262911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson fixed_queue_enqueue(p_fcrb->srej_rcv_hold_q, p_buf); 1263911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_fcrb->srej_sent = true; 1264911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_fcr_send_S_frame(p_ccb, L2CAP_FCR_SUP_SREJ, 0); 12655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 1266911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson alarm_cancel(p_ccb->fcrb.ack_timer); 1267911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 12685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 1269911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return; 1270911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1271911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1272911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Seq number is the next expected. Clear possible reject exception in case it 1273911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson * occured */ 1274911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_fcrb->rej_sent = p_fcrb->srej_sent = false; 1275911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1276911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Adjust the next_seq, so that if the upper layer sends more data in the 1277911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson callback 1278911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson context, the received frame is acked by an I-frame. */ 1279911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_fcrb->next_seq_expected = (tx_seq + 1) & L2CAP_FCR_SEQ_MODULO; 1280911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1281911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If any SAR problem in eRTM mode, spec says disconnect. */ 1282911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (!do_sar_reassembly(p_ccb, p_buf, ctrl_word)) { 1283911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_WARNING("process_i_frame() CID: 0x%04x reassembly failed", 1284911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->local_cid); 1285911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cu_disconnect_chnl(p_ccb); 1286911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return; 1287911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1288911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1289911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* RR optimization - if peer can still send us more, then start an ACK timer 1290911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson */ 1291911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson num_to_ack = (p_fcrb->next_seq_expected - p_fcrb->last_ack_sent) & 1292911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_FCR_SEQ_MODULO; 1293911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1294911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((num_to_ack < p_ccb->fcrb.max_held_acks) && (!p_fcrb->local_busy)) 1295911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson delay_ack = true; 1296911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1297911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* We should neve never ack frame if we are not in OPEN state */ 1298911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((num_to_ack != 0) && p_ccb->in_use && (p_ccb->chnl_state == CST_OPEN)) { 1299911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If no frames are awaiting transmission or are held, send an RR or RNR 1300911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson * S-frame for ack */ 1301911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (delay_ack) { 1302911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If it is the first I frame we did not ack, start ack timer */ 1303911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (!alarm_is_scheduled(p_ccb->fcrb.ack_timer)) { 1304911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson alarm_set_on_queue(p_ccb->fcrb.ack_timer, L2CAP_FCR_ACK_TIMEOUT_MS, 1305911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_fcrb_ack_timer_timeout, p_ccb, 1306911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson btu_general_alarm_queue); 1307911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1308911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else if ((fixed_queue_is_empty(p_ccb->xmit_hold_q) || 1309911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_fcr_is_flow_controlled(p_ccb)) && 1310911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson fixed_queue_is_empty(p_ccb->fcrb.srej_rcv_hold_q)) { 1311911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_fcrb->local_busy) 1312911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_fcr_send_S_frame(p_ccb, L2CAP_FCR_SUP_RNR, 0); 1313911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson else 1314911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_fcr_send_S_frame(p_ccb, L2CAP_FCR_SUP_RR, 0); 1315911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1316911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 13175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 13185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 13195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 1320ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1321ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function process_stream_frame 1322ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1323ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description This function processes frames in streaming mode 1324ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1325ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns - 1326ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1327ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 1328911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic void process_stream_frame(tL2C_CCB* p_ccb, BT_HDR* p_buf) { 1329f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(p_ccb != NULL); 1330f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(p_buf != NULL); 13315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1332911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t ctrl_word; 1333911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t fcs; 1334911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t* p; 1335911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t tx_seq; 13365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1337911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Verify FCS if using */ 1338911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->bypass_fcs != L2CAP_BYPASS_FCS) { 1339911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p = ((uint8_t*)(p_buf + 1)) + p_buf->offset + p_buf->len - L2CAP_FCS_LEN; 13405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1341911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Extract and drop the FCS from the packet */ 1342911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson STREAM_TO_UINT16(fcs, p); 1343911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf->len -= L2CAP_FCS_LEN; 13445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1345911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (l2c_fcr_rx_get_fcs(p_buf) != fcs) { 1346911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_WARNING("Rx L2CAP PDU: CID: 0x%04x BAD FCS", 1347911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->local_cid); 1348911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson osi_free(p_buf); 1349911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return; 13505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 1351911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 13525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1353911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Get the control word */ 1354911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p = ((uint8_t*)(p_buf + 1)) + p_buf->offset; 13555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1356911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson STREAM_TO_UINT16(ctrl_word, p); 13575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1358911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf->len -= L2CAP_FCR_OVERHEAD; 1359911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf->offset += L2CAP_FCR_OVERHEAD; 13605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1361911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Make sure it is an I-frame */ 1362911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (ctrl_word & L2CAP_FCR_S_FRAME_BIT) { 1363911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_WARNING( 1364911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "Rx L2CAP PDU: CID: 0x%04x BAD S-frame in streaming mode ctrl_word: " 1365911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "0x%04x", 1366911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->local_cid, ctrl_word); 1367911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson osi_free(p_buf); 1368911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return; 1369911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1370911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1371911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_EVENT( 1372911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "L2CAP eRTM Rx I-frame: cid: 0x%04x Len: %u SAR: %-12s TxSeq: %u " 1373911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "ReqSeq: %u F: %u", 1374911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->local_cid, p_buf->len, 1375911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson SAR_types[(ctrl_word & L2CAP_FCR_SAR_BITS) >> L2CAP_FCR_SAR_BITS_SHIFT], 1376911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (ctrl_word & L2CAP_FCR_TX_SEQ_BITS) >> L2CAP_FCR_TX_SEQ_BITS_SHIFT, 1377911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (ctrl_word & L2CAP_FCR_REQ_SEQ_BITS) >> L2CAP_FCR_REQ_SEQ_BITS_SHIFT, 1378911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (ctrl_word & L2CAP_FCR_F_BIT) >> L2CAP_FCR_F_BIT_SHIFT); 1379911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1380911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Extract the sequence number */ 1381911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tx_seq = (ctrl_word & L2CAP_FCR_TX_SEQ_BITS) >> L2CAP_FCR_TX_SEQ_BITS_SHIFT; 1382911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1383911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Check if tx-sequence is the expected one */ 1384911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (tx_seq != p_ccb->fcrb.next_seq_expected) { 1385911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_WARNING( 1386911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "Rx L2CAP PDU: CID: 0x%04x Lost frames Exp: %u Got: %u p_rx_sdu: " 1387911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "0x%08x", 1388911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->local_cid, p_ccb->fcrb.next_seq_expected, tx_seq, 1389911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.p_rx_sdu); 1390911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1391911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Lost one or more packets, so flush the SAR queue */ 1392911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson osi_free_and_reset((void**)&p_ccb->fcrb.p_rx_sdu); 1393911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1394911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1395911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.next_seq_expected = (tx_seq + 1) & L2CAP_FCR_SEQ_MODULO; 1396911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1397911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (!do_sar_reassembly(p_ccb, p_buf, ctrl_word)) { 1398911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Some sort of SAR error, so flush the SAR queue */ 1399911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson osi_free_and_reset((void**)&p_ccb->fcrb.p_rx_sdu); 1400911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 14015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 14025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 14035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 1404ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1405ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function do_sar_reassembly 1406ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1407ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Process SAR bits and re-assemble frame 1408ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1409ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns true if all OK, else false 1410ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1411ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 1412911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic bool do_sar_reassembly(tL2C_CCB* p_ccb, BT_HDR* p_buf, 1413911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t ctrl_word) { 1414f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(p_ccb != NULL); 1415f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(p_buf != NULL); 1416911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1417911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tL2C_FCRB* p_fcrb = &p_ccb->fcrb; 1418911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t sar_type = ctrl_word & L2CAP_FCR_SEG_BITS; 1419911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson bool packet_ok = true; 1420911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t* p; 1421911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1422911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Check if the SAR state is correct */ 1423911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((sar_type == L2CAP_FCR_UNSEG_SDU) || (sar_type == L2CAP_FCR_START_SDU)) { 1424911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_fcrb->p_rx_sdu != NULL) { 1425911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_WARNING( 1426911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "SAR - got unexpected unsegmented or start SDU Expected len: %u " 1427911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "Got so far: %u", 1428911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_fcrb->rx_sdu_len, p_fcrb->p_rx_sdu->len); 1429911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1430911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson packet_ok = false; 1431911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1432911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Check the length of the packet */ 1433911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((sar_type == L2CAP_FCR_START_SDU) && 1434911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (p_buf->len < L2CAP_SDU_LEN_OVERHEAD)) { 1435911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_WARNING("SAR start packet too short: %u", p_buf->len); 1436911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson packet_ok = false; 1437911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1438911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 1439911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_fcrb->p_rx_sdu == NULL) { 1440911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_WARNING("SAR - got unexpected cont or end SDU"); 1441911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson packet_ok = false; 1442911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1443911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1444911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1445911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((packet_ok) && (sar_type != L2CAP_FCR_UNSEG_SDU)) { 1446911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p = ((uint8_t*)(p_buf + 1)) + p_buf->offset; 1447911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1448911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* For start SDU packet, extract the SDU length */ 1449911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (sar_type == L2CAP_FCR_START_SDU) { 1450911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Get the SDU length */ 1451911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson STREAM_TO_UINT16(p_fcrb->rx_sdu_len, p); 1452911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf->offset += 2; 1453911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf->len -= 2; 1454911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1455911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_fcrb->rx_sdu_len > p_ccb->max_rx_mtu) { 1456911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_WARNING("SAR - SDU len: %u larger than MTU: %u", 1457911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_fcrb->rx_sdu_len, p_fcrb->rx_sdu_len); 1458911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson packet_ok = false; 1459911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 1460911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_fcrb->p_rx_sdu = (BT_HDR*)osi_malloc(L2CAP_MAX_BUF_SIZE); 1461911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_fcrb->p_rx_sdu->offset = OBX_BUF_MIN_OFFSET; 1462911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_fcrb->p_rx_sdu->len = 0; 1463911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1464911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1465911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1466911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (packet_ok) { 1467911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((p_fcrb->p_rx_sdu->len + p_buf->len) > p_fcrb->rx_sdu_len) { 1468911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_ERROR( 1469911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "SAR - SDU len exceeded Type: %u Lengths: %u %u %u", sar_type, 1470911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_fcrb->p_rx_sdu->len, p_buf->len, p_fcrb->rx_sdu_len); 1471911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson packet_ok = false; 1472911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else if ((sar_type == L2CAP_FCR_END_SDU) && 1473911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson ((p_fcrb->p_rx_sdu->len + p_buf->len) != p_fcrb->rx_sdu_len)) { 1474911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_WARNING("SAR - SDU end rcvd but SDU incomplete: %u %u %u", 1475911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_fcrb->p_rx_sdu->len, p_buf->len, 1476911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_fcrb->rx_sdu_len); 1477911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson packet_ok = false; 1478911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 1479911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson memcpy(((uint8_t*)(p_fcrb->p_rx_sdu + 1)) + p_fcrb->p_rx_sdu->offset + 1480911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_fcrb->p_rx_sdu->len, 1481911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p, p_buf->len); 1482911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1483911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_fcrb->p_rx_sdu->len += p_buf->len; 14845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1485911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson osi_free(p_buf); 1486911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf = NULL; 14875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1488911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (sar_type == L2CAP_FCR_END_SDU) { 1489911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf = p_fcrb->p_rx_sdu; 1490911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_fcrb->p_rx_sdu = NULL; 14915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 1492911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 14935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 1494911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 14955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1496911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (packet_ok == false) { 1497911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson osi_free(p_buf); 1498911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else if (p_buf != NULL) { 14995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_NUM_FIXED_CHNLS > 0) 1500911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->local_cid < L2CAP_BASE_APPL_CID && 1501911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (p_ccb->local_cid >= L2CAP_FIRST_FIXED_CHNL && 1502911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->local_cid <= L2CAP_LAST_FIXED_CHNL)) { 1503911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (l2cb.fixed_reg[p_ccb->local_cid - L2CAP_FIRST_FIXED_CHNL] 1504911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson .pL2CA_FixedData_Cb) 1505911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (*l2cb.fixed_reg[p_ccb->local_cid - L2CAP_FIRST_FIXED_CHNL] 1506911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson .pL2CA_FixedData_Cb)(p_ccb->local_cid, 1507911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_lcb->remote_bd_addr, p_buf); 1508911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else 15095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif 1510911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_csm_execute(p_ccb, L2CEVT_L2CAP_DATA, p_buf); 1511911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 15125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1513911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (packet_ok); 15145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 15155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 15165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 1517ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1518ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function retransmit_i_frames 1519ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1520ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description This function retransmits i-frames awaiting acks. 1521ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1522ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns bool - true if retransmitted 1523ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1524ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 1525911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic bool retransmit_i_frames(tL2C_CCB* p_ccb, uint8_t tx_seq) { 1526f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(p_ccb != NULL); 1527911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1528911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson BT_HDR* p_buf = NULL; 1529911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t* p; 1530911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t buf_seq; 1531911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t ctrl_word; 1532911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1533911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((!fixed_queue_is_empty(p_ccb->fcrb.waiting_for_ack_q)) && 1534911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (p_ccb->peer_cfg.fcr.max_transmit != 0) && 1535911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (p_ccb->fcrb.num_tries >= p_ccb->peer_cfg.fcr.max_transmit)) { 1536911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_EVENT( 1537911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "Max Tries Exceeded: (last_acq: %d CID: 0x%04x num_tries: %u (max: " 1538911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "%u) ack_q_count: %u", 1539911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.last_rx_ack, p_ccb->local_cid, p_ccb->fcrb.num_tries, 1540911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->peer_cfg.fcr.max_transmit, 1541911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson fixed_queue_length(p_ccb->fcrb.waiting_for_ack_q)); 1542911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1543911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cu_disconnect_chnl(p_ccb); 1544911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (false); 1545911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1546911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1547911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* tx_seq indicates whether to retransmit a specific sequence or all (if == 1548911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson * L2C_FCR_RETX_ALL_PKTS) */ 1549911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson list_t* list_ack = NULL; 1550911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson const list_node_t* node_ack = NULL; 1551911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (!fixed_queue_is_empty(p_ccb->fcrb.waiting_for_ack_q)) { 1552911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson list_ack = fixed_queue_get_list(p_ccb->fcrb.waiting_for_ack_q); 1553911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson node_ack = list_begin(list_ack); 1554911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1555911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (tx_seq != L2C_FCR_RETX_ALL_PKTS) { 1556911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If sending only one, the sequence number tells us which one. Look for it. 1557911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson */ 1558911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (list_ack != NULL) { 1559911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson for (; node_ack != list_end(list_ack); node_ack = list_next(node_ack)) { 1560911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf = (BT_HDR*)list_node(node_ack); 1561911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Get the old control word */ 1562911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p = ((uint8_t*)(p_buf + 1)) + p_buf->offset + L2CAP_PKT_OVERHEAD; 15635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1564911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson STREAM_TO_UINT16(ctrl_word, p); 15655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1566911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson buf_seq = 1567911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (ctrl_word & L2CAP_FCR_TX_SEQ_BITS) >> L2CAP_FCR_TX_SEQ_BITS_SHIFT; 15685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1569911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_DEBUG( 1570911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "retransmit_i_frames() cur seq: %u looking for: %u", buf_seq, 1571911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tx_seq); 15725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1573911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (tx_seq == buf_seq) break; 1574911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1575911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 15765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1577911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (!p_buf) { 1578911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_ERROR("retransmit_i_frames() UNKNOWN seq: %u q_count: %u", 1579911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tx_seq, 1580911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson fixed_queue_length(p_ccb->fcrb.waiting_for_ack_q)); 1581911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (true); 1582911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1583911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 1584911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson // Iterate though list and flush the amount requested from 1585911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson // the transmit data queue that satisfy the layer and event conditions. 1586911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson for (list_node_t* node_tmp = list_begin(p_ccb->p_lcb->link_xmit_data_q); 1587911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson node_tmp != list_end(p_ccb->p_lcb->link_xmit_data_q);) { 1588911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson BT_HDR* p_tmp = (BT_HDR*)list_node(node_tmp); 1589911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson node_tmp = list_next(node_tmp); 15905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1591911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Do not flush other CIDs or partial segments */ 1592911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((p_tmp->layer_specific == 0) && (p_tmp->event == p_ccb->local_cid)) { 1593911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson list_remove(p_ccb->p_lcb->link_xmit_data_q, p_tmp); 1594911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson osi_free(p_tmp); 1595911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 15965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 15975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1598911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Also flush our retransmission queue */ 1599911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson while (!fixed_queue_is_empty(p_ccb->fcrb.retrans_q)) 1600911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson osi_free(fixed_queue_try_dequeue(p_ccb->fcrb.retrans_q)); 16015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1602911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (list_ack != NULL) node_ack = list_begin(list_ack); 1603911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 16045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1605911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (list_ack != NULL) { 1606911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson while (node_ack != list_end(list_ack)) { 1607911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf = (BT_HDR*)list_node(node_ack); 1608911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson node_ack = list_next(node_ack); 16095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1610911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson BT_HDR* p_buf2 = l2c_fcr_clone_buf(p_buf, p_buf->offset, p_buf->len); 1611911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_buf2) { 1612911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf2->layer_specific = p_buf->layer_specific; 1613577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov 1614911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson fixed_queue_enqueue(p_ccb->fcrb.retrans_q, p_buf2); 1615911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 16165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1617911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((tx_seq != L2C_FCR_RETX_ALL_PKTS) || (p_buf2 == NULL)) break; 16185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 1619911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 16205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1621911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_link_check_send_pkts(p_ccb->p_lcb, NULL, NULL); 16225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1623911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (fixed_queue_length(p_ccb->fcrb.waiting_for_ack_q)) { 1624911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.num_tries++; 1625911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_fcr_start_timer(p_ccb); 1626911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 16275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1628911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (true); 16295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 16305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 16315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 1632ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1633ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2c_fcr_get_next_xmit_sdu_seg 1634ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1635ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Get the next SDU segment to transmit. 1636ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1637ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns pointer to buffer with segment or NULL 1638ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1639ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 1640911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsonBT_HDR* l2c_fcr_get_next_xmit_sdu_seg(tL2C_CCB* p_ccb, 1641911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t max_packet_length) { 1642f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(p_ccb != NULL); 1643911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1644911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson bool first_seg = false, /* The segment is the first part of data */ 1645911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson mid_seg = false, /* The segment is the middle part of data */ 1646911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson last_seg = false; /* The segment is the last part of data */ 1647911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t sdu_len = 0; 1648911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson BT_HDR *p_buf, *p_xmit; 1649911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t* p; 1650911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t max_pdu = p_ccb->tx_mps /* Needed? - L2CAP_MAX_HEADER_FCS*/; 1651911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1652911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If there is anything in the retransmit queue, that goes first 1653911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson */ 1654911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->fcrb.retrans_q); 1655911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_buf != NULL) { 1656911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Update Rx Seq and FCS if we acked some packets while this one was queued 1657911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson */ 1658911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson prepare_I_frame(p_ccb, p_buf, true); 16595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1660911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf->event = p_ccb->local_cid; 16615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 16625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ERTM_STATS == TRUE) 1663911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.pkts_retransmitted++; 1664911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.ertm_pkt_counts[0]++; 1665911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.ertm_byte_counts[0] += (p_buf->len - 8); 16665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif 1667911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (p_buf); 1668911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1669911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1670911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* For BD/EDR controller, max_packet_length is set to 0 */ 1671911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* For AMP controller, max_packet_length is set by available blocks */ 1672911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((max_packet_length > L2CAP_MAX_HEADER_FCS) && 1673911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (max_pdu + L2CAP_MAX_HEADER_FCS > max_packet_length)) { 1674911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson max_pdu = max_packet_length - L2CAP_MAX_HEADER_FCS; 1675911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1676911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1677911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf = (BT_HDR*)fixed_queue_try_peek_first(p_ccb->xmit_hold_q); 1678911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1679911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If there is more data than the MPS, it requires segmentation */ 1680911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_buf->len > max_pdu) { 1681911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* We are using the "event" field to tell is if we already started 1682911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson * segmentation */ 1683911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_buf->event == 0) { 1684911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson first_seg = true; 1685911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson sdu_len = p_buf->len; 1686911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else 1687911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson mid_seg = true; 16885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1689911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Get a new buffer and copy the data that can be sent in a PDU */ 1690911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_xmit = l2c_fcr_clone_buf(p_buf, L2CAP_MIN_OFFSET + L2CAP_SDU_LEN_OFFSET, 1691911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson max_pdu); 16925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1693911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_xmit != NULL) { 1694911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf->event = p_ccb->local_cid; 1695911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_xmit->event = p_ccb->local_cid; 16965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1697911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf->len -= max_pdu; 1698911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf->offset += max_pdu; 16995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1700911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* copy PBF setting */ 1701911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_xmit->layer_specific = p_buf->layer_specific; 1702911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else /* Should never happen if the application has configured buffers 1703911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson correctly */ 17045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 1705911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_ERROR( 1706911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "L2CAP - cannot get buffer for segmentation, max_pdu: %u", max_pdu); 1707911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (NULL); 1708911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1709911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else /* Use the original buffer if no segmentation, or the last segment */ 1710911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson { 1711911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_xmit = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->xmit_hold_q); 17125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1713911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_xmit->event != 0) last_seg = true; 17145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1715911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_xmit->event = p_ccb->local_cid; 1716911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 17175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1718911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Step back to add the L2CAP headers */ 1719911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_xmit->offset -= (L2CAP_PKT_OVERHEAD + L2CAP_FCR_OVERHEAD); 1720911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_xmit->len += L2CAP_PKT_OVERHEAD + L2CAP_FCR_OVERHEAD; 17215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1722911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (first_seg) { 1723911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_xmit->offset -= L2CAP_SDU_LEN_OVERHEAD; 1724911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_xmit->len += L2CAP_SDU_LEN_OVERHEAD; 1725911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 17265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1727911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Set the pointer to the beginning of the data */ 1728911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p = (uint8_t*)(p_xmit + 1) + p_xmit->offset; 17295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1730911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Now the L2CAP header */ 17315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1732911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Note: if FCS has to be included then the length is recalculated later */ 1733911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, p_xmit->len - L2CAP_PKT_OVERHEAD); 17345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1735911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, p_ccb->remote_cid); 17365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1737911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (first_seg) { 1738911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Skip control word and add SDU length */ 1739911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p += 2; 1740911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, sdu_len); 17415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1742911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* We will store the SAR type in layer-specific */ 1743911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* layer_specific is shared with flushable flag(bits 0-1), don't clear it */ 1744911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_xmit->layer_specific |= L2CAP_FCR_START_SDU; 17455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1746911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson first_seg = false; 1747911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else if (mid_seg) 1748911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_xmit->layer_specific |= L2CAP_FCR_CONT_SDU; 1749911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson else if (last_seg) 1750911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_xmit->layer_specific |= L2CAP_FCR_END_SDU; 1751911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson else 1752911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_xmit->layer_specific |= L2CAP_FCR_UNSEG_SDU; 17535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1754911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson prepare_I_frame(p_ccb, p_xmit, false); 17555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1756911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) { 1757911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson BT_HDR* p_wack = 1758911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_fcr_clone_buf(p_xmit, HCI_DATA_PREAMBLE_SIZE, p_xmit->len); 17595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1760911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (!p_wack) { 1761911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_ERROR( 1762911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "L2CAP - no buffer for xmit cloning, CID: 0x%04x Length: %u", 1763911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->local_cid, p_xmit->len); 17645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1765911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* We will not save the FCS in case we reconfigure and change options */ 1766911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->bypass_fcs != L2CAP_BYPASS_FCS) p_xmit->len -= L2CAP_FCS_LEN; 17675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1768911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Pretend we sent it and it got lost */ 1769911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson fixed_queue_enqueue(p_ccb->fcrb.waiting_for_ack_q, p_xmit); 1770911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (NULL); 1771911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 17725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ERTM_STATS == TRUE) 1773911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* set timestamp at the end of tx I-frame to get acking delay */ 1774911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* 1775911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson * NOTE: Here we assume the allocate buffer is large enough 1776911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson * to include extra 4 octets at the end. 1777911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson */ 1778911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p = ((uint8_t*)(p_wack + 1)) + p_wack->offset + p_wack->len; 1779911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT32_TO_STREAM(p, time_get_os_boottime_ms()); 17805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif 1781911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* We will not save the FCS in case we reconfigure and change options */ 1782911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->bypass_fcs != L2CAP_BYPASS_FCS) p_wack->len -= L2CAP_FCS_LEN; 17835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1784911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_wack->layer_specific = p_xmit->layer_specific; 1785911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson fixed_queue_enqueue(p_ccb->fcrb.waiting_for_ack_q, p_wack); 1786911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 17875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 17885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ERTM_STATS == TRUE) 1789911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.ertm_pkt_counts[0]++; 1790911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.ertm_byte_counts[0] += (p_xmit->len - 8); 17915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif 1792911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 17935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1794911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (p_xmit); 17955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 17965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 17976721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar/******************************************************************************* 1798ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1799ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2c_lcc_get_next_xmit_sdu_seg 1800ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 18019ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Description Get the next SDU segment to transmit for LE connection 18029ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * oriented channel 1803ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1804ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns pointer to buffer with segment or NULL 1805ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1806ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 1807911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsonBT_HDR* l2c_lcc_get_next_xmit_sdu_seg(tL2C_CCB* p_ccb, 1808911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t max_packet_length) { 1809911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson bool first_seg = false; /* The segment is the first part of data */ 1810911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson bool last_seg = false; /* The segment is the last part of data */ 1811911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t no_of_bytes_to_send = 0; 1812911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t sdu_len = 0; 1813911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson BT_HDR *p_buf, *p_xmit; 1814911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t* p; 1815911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t max_pdu = p_ccb->peer_conn_cfg.mps; 1816911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1817911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf = (BT_HDR*)fixed_queue_try_peek_first(p_ccb->xmit_hold_q); 1818911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1819911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* We are using the "event" field to tell is if we already started 1820911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson * segmentation */ 1821911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_buf->event == 0) { 1822911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson first_seg = true; 1823911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson sdu_len = p_buf->len; 1824911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_buf->len <= (max_pdu - L2CAP_LCC_SDU_LENGTH)) { 1825911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson last_seg = true; 1826911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson no_of_bytes_to_send = p_buf->len; 1827911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else 1828911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson no_of_bytes_to_send = max_pdu - L2CAP_LCC_SDU_LENGTH; 1829911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else if (p_buf->len <= max_pdu) { 1830911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson last_seg = true; 1831911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson no_of_bytes_to_send = p_buf->len; 1832911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 1833911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Middle Packet */ 1834911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson no_of_bytes_to_send = max_pdu; 1835911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1836911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1837911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Get a new buffer and copy the data that can be sent in a PDU */ 1838911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (first_seg == true) 1839911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_xmit = l2c_fcr_clone_buf(p_buf, L2CAP_LCC_OFFSET, no_of_bytes_to_send); 1840911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson else 1841911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_xmit = l2c_fcr_clone_buf(p_buf, L2CAP_MIN_OFFSET, no_of_bytes_to_send); 1842911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1843911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_xmit != NULL) { 1844911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf->event = p_ccb->local_cid; 1845911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_xmit->event = p_ccb->local_cid; 1846911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1847911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (first_seg == true) { 1848911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_xmit->offset -= L2CAP_LCC_SDU_LENGTH; /* for writing the SDU length. */ 1849911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p = (uint8_t*)(p_xmit + 1) + p_xmit->offset; 1850911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, sdu_len); 1851911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_xmit->len += L2CAP_LCC_SDU_LENGTH; 1852911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1853911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1854911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf->len -= no_of_bytes_to_send; 1855911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf->offset += no_of_bytes_to_send; 1856911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1857911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* copy PBF setting */ 1858911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_xmit->layer_specific = p_buf->layer_specific; 1859911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1860911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else /* Should never happen if the application has configured buffers 1861911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson correctly */ 1862911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson { 1863911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_ERROR("L2CAP - cannot get buffer, for segmentation"); 1864911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (NULL); 1865911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1866911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1867911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (last_seg == true) { 1868911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->xmit_hold_q); 1869911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson osi_free(p_buf); 1870911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 18716721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 1872911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Step back to add the L2CAP headers */ 1873911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_xmit->offset -= L2CAP_PKT_OVERHEAD; 1874911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_xmit->len += L2CAP_PKT_OVERHEAD; 18756721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 1876911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Set the pointer to the beginning of the data */ 1877911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p = (uint8_t*)(p_xmit + 1) + p_xmit->offset; 18786721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 1879911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Note: if FCS has to be included then the length is recalculated later */ 1880911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, p_xmit->len - L2CAP_PKT_OVERHEAD); 1881911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson UINT16_TO_STREAM(p, p_ccb->remote_cid); 1882911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (p_xmit); 18836721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar} 18845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 18855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 1886ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Configuration negotiation functions 1887ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1888ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * The following functions are used in negotiating channel modes during 1889ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * configuration 1890ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 18915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 18925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 1893ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1894ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2c_fcr_chk_chan_modes 1895ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1896ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Validates and adjusts if necessary, the FCR options 1897ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * based on remote EXT features. 1898ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1899ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Note: This assumes peer EXT Features have been received. 1900ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Basic mode is used if FCR Options have not been received 1901ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 19029ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Returns uint8_t - nonzero if can continue, '0' if no compatible 19039ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * channels 1904ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1905ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 1906911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonuint8_t l2c_fcr_chk_chan_modes(tL2C_CCB* p_ccb) { 1907f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(p_ccb != NULL); 1908ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton 1909911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Remove nonbasic options that the peer does not support */ 1910911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (!(p_ccb->p_lcb->peer_ext_fea & L2CAP_EXTFEA_ENH_RETRANS)) 1911911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->ertm_info.allowed_modes &= ~L2CAP_FCR_CHAN_OPT_ERTM; 19125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1913911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (!(p_ccb->p_lcb->peer_ext_fea & L2CAP_EXTFEA_STREAM_MODE)) 1914911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->ertm_info.allowed_modes &= ~L2CAP_FCR_CHAN_OPT_STREAM; 19155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1916911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* At least one type needs to be set (Basic, ERTM, STM) to continue */ 1917911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (!p_ccb->ertm_info.allowed_modes) { 1918911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_WARNING( 1919911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "L2CAP - Peer does not support our desired channel types"); 1920911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 19215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1922911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (p_ccb->ertm_info.allowed_modes); 19235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 19245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 19255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 1926ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1927ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2c_fcr_adj_our_req_options 1928ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1929ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Validates and sets up the FCR options passed in from 1930ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * L2CA_ConfigReq based on remote device's features. 1931ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1932ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns true if no errors, Otherwise false 1933ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1934ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 1935911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool l2c_fcr_adj_our_req_options(tL2C_CCB* p_ccb, tL2CAP_CFG_INFO* p_cfg) { 1936f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(p_ccb != NULL); 1937f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(p_cfg != NULL); 1938911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1939911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tL2CAP_FCR_OPTS* p_fcr = &p_cfg->fcr; 1940911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1941911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_fcr->mode != p_ccb->ertm_info.preferred_mode) { 1942911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_WARNING( 1943911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "l2c_fcr_adj_our_req_options - preferred_mode (%d), does not match " 1944911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "mode (%d)", 1945911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->ertm_info.preferred_mode, p_fcr->mode); 1946911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1947911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* The preferred mode is passed in through tL2CAP_ERTM_INFO, so override 1948911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson * this one */ 1949911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_fcr->mode = p_ccb->ertm_info.preferred_mode; 1950911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1951911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1952911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If upper layer did not request eRTM mode, BASIC must be used */ 1953911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->ertm_info.allowed_modes == L2CAP_FCR_CHAN_OPT_BASIC) { 1954911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_cfg->fcr_present && p_fcr->mode != L2CAP_FCR_BASIC_MODE) { 1955911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_WARNING( 1956911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "l2c_fcr_adj_our_req_options (mode %d): ERROR: No FCR options set " 1957911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "using BASIC mode", 1958911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_fcr->mode); 1959911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1960911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_fcr->mode = L2CAP_FCR_BASIC_MODE; 1961911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1962911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1963911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Process the FCR options if initial channel bring-up (not a reconfig 1964911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson *request) 1965911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson ** Determine initial channel mode to try based on our options and remote's 1966911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson *features 1967911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson */ 1968911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_cfg->fcr_present && !(p_ccb->config_done & RECONFIG_FLAG)) { 1969911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* We need to have at least one mode type common with the peer */ 1970911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (!l2c_fcr_chk_chan_modes(p_ccb)) { 1971911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Two channels have incompatible supported types */ 1972911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cu_disconnect_chnl(p_ccb); 1973911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (false); 1974911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1975911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1976911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Basic is the only common channel mode between the two devices */ 1977911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson else if (p_ccb->ertm_info.allowed_modes == L2CAP_FCR_CHAN_OPT_BASIC) { 1978911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* We only want to try Basic, so bypass sending the FCR options entirely 1979911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson */ 1980911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_cfg->fcr_present = false; 1981911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_cfg->fcs_present = false; /* Illegal to use FCS option in basic mode */ 1982911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_cfg->ext_flow_spec_present = 1983911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson false; /* Illegal to use extended flow spec in basic mode */ 1984911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1985911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1986911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* We have at least one non-basic mode available 1987911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson * Override mode from available mode options based on preference, if needed 1988911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson */ 1989911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson else { 1990911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If peer does not support STREAMING, try ERTM */ 1991911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_fcr->mode == L2CAP_FCR_STREAM_MODE && 1992911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson !(p_ccb->ertm_info.allowed_modes & L2CAP_FCR_CHAN_OPT_STREAM)) { 1993911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_DEBUG( 1994911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "L2C CFG: mode is STREAM, but peer does not support; Try ERTM"); 1995911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_fcr->mode = L2CAP_FCR_ERTM_MODE; 1996911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1997911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1998911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If peer does not support ERTM, try BASIC (will support this if made it 1999911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson * here in the code) */ 2000911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_fcr->mode == L2CAP_FCR_ERTM_MODE && 2001911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson !(p_ccb->ertm_info.allowed_modes & L2CAP_FCR_CHAN_OPT_ERTM)) { 2002911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_DEBUG( 2003911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "L2C CFG: mode is ERTM, but peer does not support; Try BASIC"); 20045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_fcr->mode = L2CAP_FCR_BASIC_MODE; 2005911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 20065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 20075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2008911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_fcr->mode != L2CAP_FCR_BASIC_MODE) { 2009911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* MTU must be smaller than buffer size */ 2010911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((p_cfg->mtu_present) && (p_cfg->mtu > p_ccb->max_rx_mtu)) { 2011911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_WARNING("L2CAP - MTU: %u larger than buf size: %u", 2012911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_cfg->mtu, p_ccb->max_rx_mtu); 2013911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (false); 2014911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 2015911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2016911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* application want to use the default MPS */ 2017911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_fcr->mps == L2CAP_DEFAULT_ERM_MPS) { 2018911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_fcr->mps = L2CAP_MPS_OVER_BR_EDR; 2019911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 2020911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* MPS must be less than MTU */ 2021911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson else if (p_fcr->mps > p_ccb->max_rx_mtu) { 2022911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_WARNING("L2CAP - MPS %u invalid MTU: %u", p_fcr->mps, 2023911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->max_rx_mtu); 2024911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (false); 2025911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 20265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2027911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* We always initially read into the HCI buffer pool, so make sure it fits 2028911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson */ 2029911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_fcr->mps > (L2CAP_MTU_SIZE - L2CAP_MAX_HEADER_FCS)) 2030911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_fcr->mps = L2CAP_MTU_SIZE - L2CAP_MAX_HEADER_FCS; 2031911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 2032911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_cfg->fcs_present = false; /* Illegal to use FCS option in basic mode */ 2033911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_cfg->ext_flow_spec_present = 2034911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson false; /* Illegal to use extended flow spec in basic mode */ 20355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 20365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2037911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->our_cfg.fcr = *p_fcr; 2038911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else /* Not sure how to send a reconfiguration(??) should fcr be included? 2039911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson */ 2040911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson { 2041911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->our_cfg.fcr_present = false; 2042911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 20435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2044911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (true); 2045911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson} 20465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 20475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 2048ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2049ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2c_fcr_adj_monitor_retran_timeout 2050ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2051ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Overrides monitor/retrans timer value based on controller 2052ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2053ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns None 2054ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2055ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 2056911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2c_fcr_adj_monitor_retran_timeout(tL2C_CCB* p_ccb) { 2057f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(p_ccb != NULL); 20585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2059911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* adjust our monitor/retran timeout */ 2060911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->out_cfg_fcr_present) { 2061911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* 2062911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson ** if we requestd ERTM or accepted ERTM 2063911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson ** We may accept ERTM even if we didn't request ERTM, in case of requesting 2064911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson *STREAM 2065911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson */ 2066911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((p_ccb->our_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) || 2067911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE)) { 2068911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* upper layer setting is ignored */ 2069911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->our_cfg.fcr.mon_tout = L2CAP_MIN_MONITOR_TOUT; 2070911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->our_cfg.fcr.rtrans_tout = L2CAP_MIN_RETRANS_TOUT; 2071911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 2072911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->our_cfg.fcr.mon_tout = 0; 2073911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->our_cfg.fcr.rtrans_tout = 0; 20745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 2075911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2076911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_DEBUG( 2077911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "l2c_fcr_adj_monitor_retran_timeout: mon_tout:%d, rtrans_tout:%d", 2078911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->our_cfg.fcr.mon_tout, p_ccb->our_cfg.fcr.rtrans_tout); 2079911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 20805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 20815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 2082ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2083ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2c_fcr_adj_our_rsp_options 2084ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2085ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Overrides any neccesary FCR options passed in from 2086ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * L2CA_ConfigRsp based on our FCR options. 2087ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Only makes adjustments if channel is in ERTM mode. 2088ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2089ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns None 2090ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2091ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 2092911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2c_fcr_adj_our_rsp_options(tL2C_CCB* p_ccb, tL2CAP_CFG_INFO* p_cfg) { 2093f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(p_ccb != NULL); 2094f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(p_cfg != NULL); 2095911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2096911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* adjust our monitor/retran timeout */ 2097911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_fcr_adj_monitor_retran_timeout(p_ccb); 2098911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2099911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_cfg->fcr_present = p_ccb->out_cfg_fcr_present; 2100911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2101911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_cfg->fcr_present) { 2102911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Temporary - until a better algorithm is implemented */ 2103911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If peer's tx_wnd_sz requires too many buffers for us to support, then 2104911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson * adjust it. For now, respond with our own tx_wnd_sz. */ 2105911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Note: peer is not guaranteed to obey our adjustment */ 2106911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->peer_cfg.fcr.tx_win_sz > p_ccb->our_cfg.fcr.tx_win_sz) { 2107911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_DEBUG("%s: adjusting requested tx_win_sz from %i to %i", 2108911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson __func__, p_ccb->peer_cfg.fcr.tx_win_sz, 2109911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->our_cfg.fcr.tx_win_sz); 2110911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->peer_cfg.fcr.tx_win_sz = p_ccb->our_cfg.fcr.tx_win_sz; 2111911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 2112911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2113911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_cfg->fcr.mode = p_ccb->peer_cfg.fcr.mode; 2114911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_cfg->fcr.tx_win_sz = p_ccb->peer_cfg.fcr.tx_win_sz; 2115911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_cfg->fcr.max_transmit = p_ccb->peer_cfg.fcr.max_transmit; 2116911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_cfg->fcr.mps = p_ccb->peer_cfg.fcr.mps; 2117911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_cfg->fcr.rtrans_tout = p_ccb->our_cfg.fcr.rtrans_tout; 2118911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_cfg->fcr.mon_tout = p_ccb->our_cfg.fcr.mon_tout; 2119911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 21205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 21215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 21225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 2123ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2124ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2c_fcr_renegotiate_chan 2125ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2126ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Called upon unsuccessful peer response to config request. 2127ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * If the error is because of the channel mode, it will try 2128ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * to resend using another supported optional channel. 2129ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2130ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns true if resent configuration, False if channel matches or 2131ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * cannot match. 2132ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2133ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 2134911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool l2c_fcr_renegotiate_chan(tL2C_CCB* p_ccb, tL2CAP_CFG_INFO* p_cfg) { 2135f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(p_ccb != NULL); 2136f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(p_cfg != NULL); 2137ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton 2138911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t peer_mode = p_ccb->our_cfg.fcr.mode; 2139911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson bool can_renegotiate; 21405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2141911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Skip if this is a reconfiguration from OPEN STATE or if FCR is not returned 2142911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson */ 2143911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (!p_cfg->fcr_present || (p_ccb->config_done & RECONFIG_FLAG)) 2144911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (false); 21455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2146911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Only retry if there are more channel options to try */ 2147911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_cfg->result == L2CAP_CFG_UNACCEPTABLE_PARAMS) { 2148911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson peer_mode = (p_cfg->fcr_present) ? p_cfg->fcr.mode : L2CAP_FCR_BASIC_MODE; 2149911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2150911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->our_cfg.fcr.mode != peer_mode) { 2151911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((--p_ccb->fcr_cfg_tries) == 0) { 2152911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_cfg->result = L2CAP_CFG_FAILED_NO_REASON; 2153911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_WARNING("l2c_fcr_renegotiate_chan (Max retries exceeded)"); 2154911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 2155911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2156911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson can_renegotiate = false; 2157911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2158911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Try another supported mode if available based on our last attempted 2159911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson * channel */ 2160911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson switch (p_ccb->our_cfg.fcr.mode) { 2161911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Our Streaming mode request was unnacceptable; try ERTM or Basic */ 2162911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson case L2CAP_FCR_STREAM_MODE: 2163911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Peer wants ERTM and we support it */ 2164911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((peer_mode == L2CAP_FCR_ERTM_MODE) && 2165911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (p_ccb->ertm_info.allowed_modes & L2CAP_FCR_CHAN_OPT_ERTM)) { 2166911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_DEBUG("l2c_fcr_renegotiate_chan(Trying ERTM)"); 2167911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->our_cfg.fcr.mode = L2CAP_FCR_ERTM_MODE; 2168911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson can_renegotiate = true; 2169911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else /* Falls through */ 2170911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2171911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson case L2CAP_FCR_ERTM_MODE: { 2172911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* We can try basic for any other peer mode if we support it */ 2173911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->ertm_info.allowed_modes & L2CAP_FCR_CHAN_OPT_BASIC) { 2174911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_DEBUG("l2c_fcr_renegotiate_chan(Trying Basic)"); 2175911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson can_renegotiate = true; 2176911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->our_cfg.fcr.mode = L2CAP_FCR_BASIC_MODE; 2177911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 2178911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } break; 21795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2180911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson default: 2181911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* All other scenarios cannot be renegotiated */ 2182911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson break; 2183911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 21845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2185911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (can_renegotiate) { 2186911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->our_cfg.fcr_present = true; 21875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2188911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->our_cfg.fcr.mode == L2CAP_FCR_BASIC_MODE) { 2189911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->our_cfg.fcs_present = false; 2190911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->our_cfg.ext_flow_spec_present = false; 21915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2192911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Basic Mode uses ACL Data Pool, make sure the MTU fits */ 2193911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((p_cfg->mtu_present) && (p_cfg->mtu > L2CAP_MTU_SIZE)) { 2194911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_WARNING("L2CAP - adjust MTU: %u too large", p_cfg->mtu); 2195911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_cfg->mtu = L2CAP_MTU_SIZE; 2196911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 21975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 21985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2199911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cu_process_our_cfg_req(p_ccb, &p_ccb->our_cfg); 2200911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cu_send_peer_config_req(p_ccb, &p_ccb->our_cfg); 2201911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson alarm_set_on_queue(p_ccb->l2c_ccb_timer, L2CAP_CHNL_CFG_TIMEOUT_MS, 2202911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2c_ccb_timer_timeout, p_ccb, 2203911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson btu_general_alarm_queue); 2204911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (true); 2205911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 22065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 2207911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 22085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2209911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Disconnect if the channels do not match */ 2210911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->our_cfg.fcr.mode != peer_mode) { 2211911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_WARNING("L2C CFG: Channels incompatible (local %d, peer %d)", 2212911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->our_cfg.fcr.mode, peer_mode); 2213911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson l2cu_disconnect_chnl(p_ccb); 2214911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 22155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2216911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (false); 2217911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson} 22185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 22195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 2220ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2221ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2c_fcr_process_peer_cfg_req 2222ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2223ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description This function is called to process the FCR options passed 2224ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * in the peer's configuration request. 2225ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2226ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns uint8_t - L2CAP_PEER_CFG_OK, L2CAP_PEER_CFG_UNACCEPTABLE, 2227ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * or L2CAP_PEER_CFG_DISCONNECT. 2228ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2229ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 2230911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonuint8_t l2c_fcr_process_peer_cfg_req(tL2C_CCB* p_ccb, tL2CAP_CFG_INFO* p_cfg) { 2231f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(p_ccb != NULL); 2232f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(p_cfg != NULL); 2233911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2234911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t max_retrans_size; 2235911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t fcr_ok = L2CAP_PEER_CFG_OK; 2236911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2237911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_lcb->w4_info_rsp = 2238911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson false; /* Handles T61x SonyEricsson Bug in Info Request */ 2239911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2240911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_EVENT( 2241911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "l2c_fcr_process_peer_cfg_req() CFG fcr_present:%d fcr.mode:%d CCB FCR " 2242911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "mode:%d preferred: %u allowed:%u", 2243911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_cfg->fcr_present, p_cfg->fcr.mode, p_ccb->our_cfg.fcr.mode, 2244911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->ertm_info.preferred_mode, p_ccb->ertm_info.allowed_modes); 2245911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2246911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If Peer wants basic, we are done (accept it or disconnect) */ 2247911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_cfg->fcr.mode == L2CAP_FCR_BASIC_MODE) { 2248911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If we do not allow basic, disconnect */ 2249911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (!(p_ccb->ertm_info.allowed_modes & L2CAP_FCR_CHAN_OPT_BASIC)) 2250911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson fcr_ok = L2CAP_PEER_CFG_DISCONNECT; 2251911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 2252911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2253911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Need to negotiate if our modes are not the same */ 2254911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson else if (p_cfg->fcr.mode != p_ccb->ertm_info.preferred_mode) { 2255911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If peer wants a mode that we don't support then retry our mode (ex. 2256911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson *rtx/flc), OR 2257911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson ** If we want ERTM and they wanted streaming retry our mode. 2258911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson ** Note: If we have already determined they support our mode previously 2259911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson ** from their EXF mask. 2260911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson */ 2261911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((((1 << p_cfg->fcr.mode) & L2CAP_FCR_CHAN_OPT_ALL_MASK) == 0) || 2262911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (p_ccb->ertm_info.preferred_mode == L2CAP_FCR_ERTM_MODE)) { 2263911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_cfg->fcr.mode = p_ccb->our_cfg.fcr.mode; 2264911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_cfg->fcr.tx_win_sz = p_ccb->our_cfg.fcr.tx_win_sz; 2265911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_cfg->fcr.max_transmit = p_ccb->our_cfg.fcr.max_transmit; 2266911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson fcr_ok = L2CAP_PEER_CFG_UNACCEPTABLE; 2267911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 2268911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2269911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If we wanted basic, then try to renegotiate it */ 2270911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson else if (p_ccb->ertm_info.preferred_mode == L2CAP_FCR_BASIC_MODE) { 2271911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_cfg->fcr.mode = L2CAP_FCR_BASIC_MODE; 2272911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_cfg->fcr.max_transmit = p_cfg->fcr.tx_win_sz = 0; 2273911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_cfg->fcr.rtrans_tout = p_cfg->fcr.mon_tout = p_cfg->fcr.mps = 0; 2274911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->our_cfg.fcr.rtrans_tout = p_ccb->our_cfg.fcr.mon_tout = 2275911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->our_cfg.fcr.mps = 0; 2276911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson fcr_ok = L2CAP_PEER_CFG_UNACCEPTABLE; 2277911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 2278911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2279911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Only other valid case is if they want ERTM and we wanted STM which should 2280911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson be 2281911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson accepted if we support it; otherwise the channel should be disconnected 2282911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson */ 2283911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson else if ((p_cfg->fcr.mode != L2CAP_FCR_ERTM_MODE) || 2284911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson !(p_ccb->ertm_info.allowed_modes & L2CAP_FCR_CHAN_OPT_ERTM)) { 2285911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson fcr_ok = L2CAP_PEER_CFG_DISCONNECT; 2286911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 2287911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 2288911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2289911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Configuration for FCR channels so make any adjustments and fwd to upper 2290911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson * layer */ 2291911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (fcr_ok == L2CAP_PEER_CFG_OK) { 2292911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* by default don't need to send params in the response */ 2293911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->out_cfg_fcr_present = false; 2294911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2295911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Make any needed adjustments for the response to the peer */ 2296911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_cfg->fcr_present && p_cfg->fcr.mode != L2CAP_FCR_BASIC_MODE) { 2297911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Peer desires to bypass FCS check, and streaming or ERTM mode */ 2298911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_cfg->fcs_present) { 2299911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->peer_cfg.fcs = p_cfg->fcs; 2300911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->peer_cfg_bits |= L2CAP_CH_CFG_MASK_FCS; 2301911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_cfg->fcs == L2CAP_CFG_FCS_BYPASS) 2302911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->bypass_fcs |= L2CAP_CFG_FCS_PEER; 2303911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 2304911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2305911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson max_retrans_size = p_ccb->ertm_info.fcr_tx_buf_size - sizeof(BT_HDR) - 2306911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_MIN_OFFSET - L2CAP_SDU_LEN_OFFSET - 2307911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_FCS_LEN; 2308911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2309911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Ensure the MPS is not bigger than the MTU */ 2310911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((p_cfg->fcr.mps == 0) || (p_cfg->fcr.mps > p_ccb->peer_cfg.mtu)) { 2311911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_cfg->fcr.mps = p_ccb->peer_cfg.mtu; 2312911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->out_cfg_fcr_present = true; 2313911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 2314911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2315911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Ensure the MPS is not bigger than our retransmission buffer */ 2316911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_cfg->fcr.mps > max_retrans_size) { 2317911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_TRACE_DEBUG("CFG: Overriding MPS to %d (orig %d)", 2318911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson max_retrans_size, p_cfg->fcr.mps); 2319911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2320911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_cfg->fcr.mps = max_retrans_size; 2321911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->out_cfg_fcr_present = true; 2322911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 2323911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2324911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_cfg->fcr.mode == L2CAP_FCR_ERTM_MODE || 2325911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_cfg->fcr.mode == L2CAP_FCR_STREAM_MODE) { 2326911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Always respond with FCR ERTM parameters */ 2327911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->out_cfg_fcr_present = true; 2328911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 2329911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 2330911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2331911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Everything ok, so save the peer's adjusted fcr options */ 2332911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->peer_cfg.fcr = p_cfg->fcr; 2333911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2334911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_cfg->fcr_present) p_ccb->peer_cfg_bits |= L2CAP_CH_CFG_MASK_FCR; 2335911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else if (fcr_ok == L2CAP_PEER_CFG_UNACCEPTABLE) { 2336911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Allow peer only one retry for mode */ 2337911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->peer_cfg_already_rejected) 2338911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson fcr_ok = L2CAP_PEER_CFG_DISCONNECT; 2339911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson else 2340911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->peer_cfg_already_rejected = true; 2341911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 23425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2343911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (fcr_ok); 23445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 23455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 23465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ERTM_STATS == TRUE) 23475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 2348ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2349ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2c_fcr_collect_ack_delay 2350ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2351ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description collect throughput, delay, queue size of waiting ack 2352ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2353ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Parameters 2354ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * tL2C_CCB 2355ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2356ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns void 2357ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2358ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 2359911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic void l2c_fcr_collect_ack_delay(tL2C_CCB* p_ccb, uint8_t num_bufs_acked) { 2360911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint32_t index; 2361911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson BT_HDR* p_buf; 2362911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t* p; 2363911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint32_t timestamp, delay; 2364911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t xx; 2365911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t str[120]; 2366911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2367911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson index = p_ccb->fcrb.ack_delay_avg_index; 2368911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2369911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* update sum, max and min of waiting for ack queue size */ 2370911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.ack_q_count_avg[index] += 2371911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson fixed_queue_length(p_ccb->fcrb.waiting_for_ack_q); 2372911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2373911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (fixed_queue_length(p_ccb->fcrb.waiting_for_ack_q) > 2374911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.ack_q_count_max[index]) 2375911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.ack_q_count_max[index] = 23761a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov fixed_queue_length(p_ccb->fcrb.waiting_for_ack_q); 23775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2378911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (fixed_queue_length(p_ccb->fcrb.waiting_for_ack_q) < 2379911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.ack_q_count_min[index]) 2380911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.ack_q_count_min[index] = 2381911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson fixed_queue_length(p_ccb->fcrb.waiting_for_ack_q); 2382911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2383911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* update sum, max and min of round trip delay of acking */ 2384911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson list_t* list = NULL; 2385911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (!fixed_queue_is_empty(p_ccb->fcrb.waiting_for_ack_q)) 2386911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson list = fixed_queue_get_list(p_ccb->fcrb.waiting_for_ack_q); 2387911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (list != NULL) { 2388911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson for (const list_node_t *node = list_begin(list), xx = 0; 2389911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (node != list_end(list)) && (xx < num_bufs_acked); 2390911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson node = list_next(node), xx++) { 2391911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf = list_node(node); 2392911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* adding up length of acked I-frames to get throughput */ 2393911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.throughput[index] += p_buf->len - 8; 2394911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2395911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (xx == num_bufs_acked - 1) { 2396911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* get timestamp from tx I-frame that receiver is acking */ 2397911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p = ((uint8_t*)(p_buf + 1)) + p_buf->offset + p_buf->len; 2398911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->bypass_fcs != L2CAP_BYPASS_FCS) { 2399911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p += L2CAP_FCS_LEN; 24005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 24015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2402911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson STREAM_TO_UINT32(timestamp, p); 2403911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson delay = time_get_os_boottime_ms() - timestamp; 24045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2405911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.ack_delay_avg[index] += delay; 2406911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (delay > p_ccb->fcrb.ack_delay_max[index]) 2407911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.ack_delay_max[index] = delay; 2408911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (delay < p_ccb->fcrb.ack_delay_min[index]) 2409911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.ack_delay_min[index] = delay; 2410911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 2411911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 2412911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 24135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2414911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.ack_delay_avg_count++; 24155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2416911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* calculate average and initialize next avg, min and max */ 2417911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->fcrb.ack_delay_avg_count > L2CAP_ERTM_STATS_AVG_NUM_SAMPLES) { 2418911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.ack_delay_avg_count = 0; 24195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2420911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.ack_q_count_avg[index] /= L2CAP_ERTM_STATS_AVG_NUM_SAMPLES; 2421911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.ack_delay_avg[index] /= L2CAP_ERTM_STATS_AVG_NUM_SAMPLES; 24225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2423911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* calculate throughput */ 2424911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson timestamp = time_get_os_boottime_ms(); 2425911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (timestamp - p_ccb->fcrb.throughput_start > 0) 2426911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.throughput[index] /= 2427911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (timestamp - p_ccb->fcrb.throughput_start); 24285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2429911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.throughput_start = timestamp; 24305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2431911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson snprintf( 2432911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson str, sizeof(str), 2433911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "[%02u] throughput: %5u, ack_delay avg:%3u, min:%3u, max:%3u, " 2434911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "ack_q_count avg:%3u, min:%3u, max:%3u", 2435911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson index, p_ccb->fcrb.throughput[index], p_ccb->fcrb.ack_delay_avg[index], 2436911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.ack_delay_min[index], p_ccb->fcrb.ack_delay_max[index], 2437911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.ack_q_count_avg[index], p_ccb->fcrb.ack_q_count_min[index], 2438911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.ack_q_count_max[index]); 24395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2440911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson BT_TRACE(TRACE_CTRL_GENERAL | TRACE_LAYER_GKI | TRACE_ORG_GKI, 2441911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson TRACE_TYPE_GENERIC, "%s", str); 24425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2443911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson index = (index + 1) % L2CAP_ERTM_STATS_NUM_AVG; 2444911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.ack_delay_avg_index = index; 24455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2446911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.ack_q_count_max[index] = 0; 2447911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.ack_q_count_min[index] = 0xFFFFFFFF; 2448911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.ack_q_count_avg[index] = 0; 24495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2450911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.ack_delay_max[index] = 0; 2451911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.ack_delay_min[index] = 0xFFFFFFFF; 2452911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.ack_delay_avg[index] = 0; 2453911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2454911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->fcrb.throughput[index] = 0; 2455911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 24565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 24575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif 2458