l2c_fcr.cc revision 9ca07091a1f07ea201cee0504dab6a1d7073d429
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 26ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton#include <assert.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 315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "bt_types.h" 32258c2538e3b62a8cdb403f2730c45d721e5292b4Pavlin Radoslavov#include "bt_common.h" 335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "hcimsgs.h" 345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "l2c_api.h" 35ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton#include "l2c_int.h" 36ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton#include "l2cdefs.h" 375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "btm_api.h" 385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "btm_int.h" 39ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton#include "btu.h" 405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 4178bcff79e1b1f0efce436b33bdd6da88745bfc8aPavlin Radoslavov 4278bcff79e1b1f0efce436b33bdd6da88745bfc8aPavlin Radoslavovextern fixed_queue_t *btu_general_alarm_queue; 4378bcff79e1b1f0efce436b33bdd6da88745bfc8aPavlin Radoslavov 449ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson/* Flag passed to retransmit_i_frames() when all packets should be retransmitted 459ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson */ 465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#define L2C_FCR_RETX_ALL_PKTS 0xFF 475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 482e3d006b96eafb0651fe7f78d28250faf89405dePavlin Radoslavov/* this is the minimal offset required by OBX to process incoming packets */ 492e3d006b96eafb0651fe7f78d28250faf89405dePavlin Radoslavovstatic const uint16_t OBX_BUF_MIN_OFFSET = 4; 502e3d006b96eafb0651fe7f78d28250faf89405dePavlin Radoslavov 51a1e7e5561026e32c5f4d51bf6102fd275061b80fMarie Janssenstatic const char *SAR_types[] = { "Unsegmented", "Start", "End", "Continuation" }; 52a1e7e5561026e32c5f4d51bf6102fd275061b80fMarie Janssenstatic 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] = { 565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241, 575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440, 585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40, 595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841, 605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40, 615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41, 625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641, 635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040, 645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240, 655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441, 665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41, 675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840, 685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41, 695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40, 705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640, 715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041, 725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240, 735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441, 745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41, 755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840, 765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41, 775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40, 785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640, 795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041, 805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241, 815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440, 825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40, 835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841, 845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40, 855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41, 865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641, 875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040, 885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}; 895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 92ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Static local functions 935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*/ 94d19e0785e662e640191a075eda07acce61c2aedaMarie Janssenstatic bool process_reqseq (tL2C_CCB *p_ccb, uint16_t ctrl_word); 95d19e0785e662e640191a075eda07acce61c2aedaMarie Janssenstatic void process_s_frame (tL2C_CCB *p_ccb, BT_HDR *p_buf, uint16_t ctrl_word); 96d19e0785e662e640191a075eda07acce61c2aedaMarie Janssenstatic void process_i_frame (tL2C_CCB *p_ccb, BT_HDR *p_buf, uint16_t ctrl_word, bool delay_ack); 97d19e0785e662e640191a075eda07acce61c2aedaMarie Janssenstatic bool retransmit_i_frames (tL2C_CCB *p_ccb, uint8_t tx_seq); 98d19e0785e662e640191a075eda07acce61c2aedaMarie Janssenstatic void prepare_I_frame (tL2C_CCB *p_ccb, BT_HDR *p_buf, bool is_retransmission); 995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic void process_stream_frame (tL2C_CCB *p_ccb, BT_HDR *p_buf); 100d19e0785e662e640191a075eda07acce61c2aedaMarie Janssenstatic bool do_sar_reassembly (tL2C_CCB *p_ccb, BT_HDR *p_buf, uint16_t ctrl_word); 1015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ERTM_STATS == TRUE) 103d19e0785e662e640191a075eda07acce61c2aedaMarie Janssenstatic void l2c_fcr_collect_ack_delay (tL2C_CCB *p_ccb, uint8_t num_bufs_acked); 1045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif 1055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 107ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 108ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2c_fcr_updcrc 109ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 110ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description This function computes the CRC using the look-up table. 111ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 112ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns CRC 113ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 114ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 115ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Mantonstatic unsigned short l2c_fcr_updcrc(unsigned short icrc, unsigned char *icp, int icnt) 1165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{ 117b2a292b5d8df2f359c38b0787bc01181225a9bc9Pavlin Radoslavov unsigned short crc = icrc; 118b2a292b5d8df2f359c38b0787bc01181225a9bc9Pavlin Radoslavov unsigned char *cp = icp; 119b2a292b5d8df2f359c38b0787bc01181225a9bc9Pavlin Radoslavov int cnt = icnt; 1205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project while (cnt--) 1225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 1235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project crc = ((crc >> 8) & 0xff) ^ crctab[(crc & 0xff) ^ *cp++]; 1245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 1255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project return(crc); 1275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 1285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 131ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 132ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2c_fcr_tx_get_fcs 133ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 134ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description This function computes the CRC for a frame to be TXed. 135ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 136ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns CRC 137ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 138ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 139d19e0785e662e640191a075eda07acce61c2aedaMarie Janssenstatic uint16_t l2c_fcr_tx_get_fcs (BT_HDR *p_buf) 1405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{ 141d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen uint8_t *p = ((uint8_t *) (p_buf + 1)) + p_buf->offset; 1425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project return (l2c_fcr_updcrc (L2CAP_FCR_INIT_CRC, p, p_buf->len)); 1445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 1455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 147ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 148ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2c_fcr_rx_get_fcs 149ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 150ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description This function computes the CRC for a received frame. 151ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 152ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns CRC 153ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 154ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 155d19e0785e662e640191a075eda07acce61c2aedaMarie Janssenstatic uint16_t l2c_fcr_rx_get_fcs (BT_HDR *p_buf) 1565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{ 157d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen uint8_t *p = ((uint8_t *) (p_buf + 1)) + p_buf->offset; 1585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* offset points past the L2CAP header, but the CRC check includes it */ 1605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p -= L2CAP_PKT_OVERHEAD; 1615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project return (l2c_fcr_updcrc (L2CAP_FCR_INIT_CRC, p, p_buf->len + L2CAP_PKT_OVERHEAD)); 1635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 1645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 166ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 167ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2c_fcr_start_timer 168ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 169ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description This function starts the (monitor or retransmission) timer. 170ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 171ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns - 172ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 173ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 1745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectvoid l2c_fcr_start_timer (tL2C_CCB *p_ccb) 1755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{ 176ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton assert(p_ccb != NULL); 177d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen uint32_t tout; 1785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* The timers which are in milliseconds */ 1805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (p_ccb->fcrb.wait_ack) 1815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 182d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen tout = (uint32_t)p_ccb->our_cfg.fcr.mon_tout; 1835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 1845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project else 1855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 186d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen tout = (uint32_t)p_ccb->our_cfg.fcr.rtrans_tout; 1875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 188ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton 1895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Only start a timer that was not started */ 19078bcff79e1b1f0efce436b33bdd6da88745bfc8aPavlin Radoslavov if (!alarm_is_scheduled(p_ccb->fcrb.mon_retrans_timer)) { 19178bcff79e1b1f0efce436b33bdd6da88745bfc8aPavlin Radoslavov alarm_set_on_queue(p_ccb->fcrb.mon_retrans_timer, tout, 19278bcff79e1b1f0efce436b33bdd6da88745bfc8aPavlin Radoslavov l2c_ccb_timer_timeout, p_ccb, 19378bcff79e1b1f0efce436b33bdd6da88745bfc8aPavlin Radoslavov btu_general_alarm_queue); 19478bcff79e1b1f0efce436b33bdd6da88745bfc8aPavlin Radoslavov } 1955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 1965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 198ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 199ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2c_fcr_stop_timer 200ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 201ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description This function stops the (monitor or transmission) timer. 202ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 203ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns - 204ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 205ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 2065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectvoid l2c_fcr_stop_timer (tL2C_CCB *p_ccb) 2075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{ 208ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton assert(p_ccb != NULL); 20978bcff79e1b1f0efce436b33bdd6da88745bfc8aPavlin Radoslavov alarm_cancel(p_ccb->fcrb.mon_retrans_timer); 2105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 2115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 213ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 214ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2c_fcr_cleanup 215ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2169ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Description This function cleans up the variable used for 2179ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * flow-control/retrans. 218ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 219ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns - 220ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 221ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 2225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectvoid l2c_fcr_cleanup (tL2C_CCB *p_ccb) 2235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{ 224ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton assert(p_ccb != NULL); 2255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project tL2C_FCRB *p_fcrb = &p_ccb->fcrb; 2265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 22778bcff79e1b1f0efce436b33bdd6da88745bfc8aPavlin Radoslavov alarm_free(p_fcrb->mon_retrans_timer); 22878bcff79e1b1f0efce436b33bdd6da88745bfc8aPavlin Radoslavov p_fcrb->mon_retrans_timer = NULL; 22978bcff79e1b1f0efce436b33bdd6da88745bfc8aPavlin Radoslavov alarm_free(p_fcrb->ack_timer); 23078bcff79e1b1f0efce436b33bdd6da88745bfc8aPavlin Radoslavov p_fcrb->ack_timer = NULL; 2315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 232cceb430489a70add1b996d54289867c17f4ac0fdPavlin Radoslavov osi_free_and_reset((void **)&p_fcrb->p_rx_sdu); 2335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 234072bd753e6ac2a011421cd7e4a2e622ee7d052fcAndre Eisenbach fixed_queue_free(p_fcrb->waiting_for_ack_q, osi_free); 2351a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov p_fcrb->waiting_for_ack_q = NULL; 2365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 237072bd753e6ac2a011421cd7e4a2e622ee7d052fcAndre Eisenbach fixed_queue_free(p_fcrb->srej_rcv_hold_q, osi_free); 2381a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov p_fcrb->srej_rcv_hold_q = NULL; 2395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 240072bd753e6ac2a011421cd7e4a2e622ee7d052fcAndre Eisenbach fixed_queue_free(p_fcrb->retrans_q, osi_free); 2411a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov p_fcrb->retrans_q = NULL; 2425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ERTM_STATS == TRUE) 2445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if ( (p_ccb->local_cid >= L2CAP_BASE_APPL_CID) && (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) ) 2455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 246d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen uint32_t dur = time_get_os_boottime_ms() - p_ccb->fcrb.connect_tick_count; 24780d7f60680f483a71e413f2453ab20013aff5c5cGeorge Burgess IV size_t p_str_size = 120; 24880d7f60680f483a71e413f2453ab20013aff5c5cGeorge Burgess IV char *p_str = (char *)osi_malloc(p_str_size); 249d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen uint16_t i; 250d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen uint32_t throughput_avg, ack_delay_avg, ack_q_count_avg; 2515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2520212487880be33e255d49f6e38dbb035d1f77750Sharvil Nanavati BT_TRACE(TRACE_CTRL_GENERAL | TRACE_LAYER_GKI | TRACE_ORG_GKI , TRACE_TYPE_GENERIC, 2535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project "--- L2CAP ERTM Stats for CID: 0x%04x Duration: %08ums", p_ccb->local_cid, dur); 2540212487880be33e255d49f6e38dbb035d1f77750Sharvil Nanavati BT_TRACE(TRACE_CTRL_GENERAL | TRACE_LAYER_GKI | TRACE_ORG_GKI , TRACE_TYPE_GENERIC, 2555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project "Retransmissions:%08u Times Flow Controlled:%08u Retrans Touts:%08u Ack Touts:%08u", 2565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->fcrb.pkts_retransmitted, p_ccb->fcrb.xmit_window_closed, p_ccb->fcrb.retrans_touts, p_ccb->fcrb.xmit_ack_touts); 2570212487880be33e255d49f6e38dbb035d1f77750Sharvil Nanavati BT_TRACE(TRACE_CTRL_GENERAL | TRACE_LAYER_GKI | TRACE_ORG_GKI , TRACE_TYPE_GENERIC, 2585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project "Times there is less than 2 packets in controller when flow controlled:%08u", p_ccb->fcrb.controller_idle); 2590212487880be33e255d49f6e38dbb035d1f77750Sharvil Nanavati BT_TRACE(TRACE_CTRL_GENERAL | TRACE_LAYER_GKI | TRACE_ORG_GKI , TRACE_TYPE_GENERIC, 2605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project "max_held_acks:%08u, in_cfg.fcr.tx_win_sz:%08u", p_ccb->fcrb.max_held_acks, p_ccb->peer_cfg.fcr.tx_win_sz ); 261717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov 26280d7f60680f483a71e413f2453ab20013aff5c5cGeorge Burgess IV snprintf(p_str, p_str_size, "Sent Pkts:%08u Bytes:%10u(%06u/sec) RR:%08u REJ:%08u RNR:%08u SREJ:%08u", 2635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->fcrb.ertm_pkt_counts[0], p_ccb->fcrb.ertm_byte_counts[0], 2645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project (dur >= 10 ? (p_ccb->fcrb.ertm_byte_counts[0] * 100) / (dur / 10) : 0), 2655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->fcrb.s_frames_sent[0], p_ccb->fcrb.s_frames_sent[1], p_ccb->fcrb.s_frames_sent[2], p_ccb->fcrb.s_frames_sent[3]); 2665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 267717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov BT_TRACE(TRACE_CTRL_GENERAL | TRACE_LAYER_GKI | TRACE_ORG_GKI , TRACE_TYPE_GENERIC, "%s", p_str); 2685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 26980d7f60680f483a71e413f2453ab20013aff5c5cGeorge Burgess IV snprintf(p_str, p_str_size, "Rcvd Pkts:%08u Bytes:%10u(%06u/sec) RR:%08u REJ:%08u RNR:%08u SREJ:%08u", 2705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->fcrb.ertm_pkt_counts[1], p_ccb->fcrb.ertm_byte_counts[1], 2715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project (dur >= 10 ? (p_ccb->fcrb.ertm_byte_counts[1] * 100) / (dur / 10) : 0), 2725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->fcrb.s_frames_rcvd[0], p_ccb->fcrb.s_frames_rcvd[1], p_ccb->fcrb.s_frames_rcvd[2], p_ccb->fcrb.s_frames_rcvd[3]); 2735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 274717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov BT_TRACE(TRACE_CTRL_GENERAL | TRACE_LAYER_GKI | TRACE_ORG_GKI , TRACE_TYPE_GENERIC, "%s", p_str); 2755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 276717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov throughput_avg = 0; 277717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov ack_delay_avg = 0; 278717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov ack_q_count_avg = 0; 2795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 280717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov for (i = 0; i < L2CAP_ERTM_STATS_NUM_AVG; i++) { 281717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov if (i == p_ccb->fcrb.ack_delay_avg_index) { 282717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov BT_TRACE(TRACE_CTRL_GENERAL | TRACE_LAYER_GKI | TRACE_ORG_GKI , TRACE_TYPE_GENERIC, 283717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov "[%02u] collecting data ...", i ); 284717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov continue; 285717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov } 2865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 28780d7f60680f483a71e413f2453ab20013aff5c5cGeorge Burgess IV snprintf(p_str, p_str_size, "[%02u] throughput: %5u, ack_delay avg:%3u, min:%3u, max:%3u, ack_q_count avg:%3u, min:%3u, max:%3u", 288717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov i, p_ccb->fcrb.throughput[i], 289717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov p_ccb->fcrb.ack_delay_avg[i], p_ccb->fcrb.ack_delay_min[i], p_ccb->fcrb.ack_delay_max[i], 290717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov p_ccb->fcrb.ack_q_count_avg[i], p_ccb->fcrb.ack_q_count_min[i], p_ccb->fcrb.ack_q_count_max[i] ); 2915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 292717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov BT_TRACE(TRACE_CTRL_GENERAL | TRACE_LAYER_GKI | TRACE_ORG_GKI , TRACE_TYPE_GENERIC, "%s", p_str); 2935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 294717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov throughput_avg += p_ccb->fcrb.throughput[i]; 295717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov ack_delay_avg += p_ccb->fcrb.ack_delay_avg[i]; 296717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov ack_q_count_avg += p_ccb->fcrb.ack_q_count_avg[i]; 297717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov } 2985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 299717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov throughput_avg /= (L2CAP_ERTM_STATS_NUM_AVG - 1); 300717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov ack_delay_avg /= (L2CAP_ERTM_STATS_NUM_AVG - 1); 301717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov ack_q_count_avg /= (L2CAP_ERTM_STATS_NUM_AVG - 1); 3025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 303717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov BT_TRACE(TRACE_CTRL_GENERAL | TRACE_LAYER_GKI | TRACE_ORG_GKI , TRACE_TYPE_GENERIC, 304717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov "throughput_avg: %8u (kbytes/sec), ack_delay_avg: %8u ms, ack_q_count_avg: %8u", 305717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov throughput_avg, ack_delay_avg, ack_q_count_avg ); 3065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 307717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov osi_free(p_str); 3085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 3090212487880be33e255d49f6e38dbb035d1f77750Sharvil Nanavati BT_TRACE(TRACE_CTRL_GENERAL | TRACE_LAYER_GKI | TRACE_ORG_GKI , TRACE_TYPE_GENERIC, 3105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project "---"); 3115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 3125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif 3135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 3145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project memset (p_fcrb, 0, sizeof (tL2C_FCRB)); 3155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 3165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 3175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 318ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 319ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2c_fcr_clone_buf 320ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 3219ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Description This function allocates and copies requested part of a 3229ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * buffer at a new-offset. 323ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 324ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns pointer to new buffer 325ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 326ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 327d19e0785e662e640191a075eda07acce61c2aedaMarie JanssenBT_HDR *l2c_fcr_clone_buf(BT_HDR *p_buf, uint16_t new_offset, uint16_t no_of_bytes) 3285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{ 329ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton assert(p_buf != NULL); 330871e9ba3063530a81ca7ff03e8433c25e1e8c096Pavlin Radoslavov /* 331871e9ba3063530a81ca7ff03e8433c25e1e8c096Pavlin Radoslavov * NOTE: We allocate extra L2CAP_FCS_LEN octets, in case we need to put 332871e9ba3063530a81ca7ff03e8433c25e1e8c096Pavlin Radoslavov * the FCS (Frame Check Sequence) at the end of the buffer. 333871e9ba3063530a81ca7ff03e8433c25e1e8c096Pavlin Radoslavov */ 334871e9ba3063530a81ca7ff03e8433c25e1e8c096Pavlin Radoslavov uint16_t buf_size = no_of_bytes + sizeof(BT_HDR) + new_offset + L2CAP_FCS_LEN; 335871e9ba3063530a81ca7ff03e8433c25e1e8c096Pavlin Radoslavov#if (L2CAP_ERTM_STATS == TRUE) 336871e9ba3063530a81ca7ff03e8433c25e1e8c096Pavlin Radoslavov /* 337871e9ba3063530a81ca7ff03e8433c25e1e8c096Pavlin Radoslavov * NOTE: If L2CAP_ERTM_STATS is enabled, we need 4 extra octets at the 338871e9ba3063530a81ca7ff03e8433c25e1e8c096Pavlin Radoslavov * end for a timestamp at the end of an I-frame. 339871e9ba3063530a81ca7ff03e8433c25e1e8c096Pavlin Radoslavov */ 340871e9ba3063530a81ca7ff03e8433c25e1e8c096Pavlin Radoslavov buf_size += sizeof(uint32_t); 341871e9ba3063530a81ca7ff03e8433c25e1e8c096Pavlin Radoslavov#endif 342cceb430489a70add1b996d54289867c17f4ac0fdPavlin Radoslavov BT_HDR *p_buf2 = (BT_HDR *)osi_malloc(buf_size); 3435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 344717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov p_buf2->offset = new_offset; 345717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov p_buf2->len = no_of_bytes; 346d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen memcpy(((uint8_t *)(p_buf2 + 1)) + p_buf2->offset, 347d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen ((uint8_t *)(p_buf + 1)) + p_buf->offset, 348717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov no_of_bytes); 3495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 3505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project return (p_buf2); 3515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 3525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 3535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 354ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 355ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2c_fcr_is_flow_controlled 356ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 357ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description This function checks if the CCB is flow controlled by peer. 358ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 359ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns The control word 360ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 361ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 362d19e0785e662e640191a075eda07acce61c2aedaMarie Janssenbool l2c_fcr_is_flow_controlled (tL2C_CCB *p_ccb) 3635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{ 364ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton assert(p_ccb != NULL); 3655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) 3665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 3675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Check if remote side flowed us off or the transmit window is full */ 368d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen if ( (p_ccb->fcrb.remote_busy == true) 3691a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov || (fixed_queue_length(p_ccb->fcrb.waiting_for_ack_q) >= p_ccb->peer_cfg.fcr.tx_win_sz) ) 3705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 3715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ERTM_STATS == TRUE) 3721a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov if (!fixed_queue_is_empty(p_ccb->xmit_hold_q)) 3735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 3745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->fcrb.xmit_window_closed++; 3755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 3765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if ((p_ccb->p_lcb->sent_not_acked < 2)&&(l2cb.controller_xmit_window > 0)) 3775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->fcrb.controller_idle++; 3785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 3795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif 380d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen return (true); 3815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 3825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 383d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen return (false); 3845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 3855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 3865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 387ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 388ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function prepare_I_frame 389ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 390ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description This function sets the FCR variables in an I-frame that is 391ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * about to be sent to HCI for transmission. This may be the 392ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * first time the I-frame is sent, or a retransmission 393ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 394ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns - 395ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 396ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 397d19e0785e662e640191a075eda07acce61c2aedaMarie Janssenstatic void prepare_I_frame (tL2C_CCB *p_ccb, BT_HDR *p_buf, bool is_retransmission) 3985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{ 399ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton assert(p_ccb != NULL); 400ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton assert(p_buf != NULL); 4015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project tL2C_FCRB *p_fcrb = &p_ccb->fcrb; 402d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen uint8_t *p; 403d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen uint16_t fcs; 404d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen uint16_t ctrl_word; 405d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen bool set_f_bit = p_fcrb->send_f_rsp; 4065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 407d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen p_fcrb->send_f_rsp = false; 4085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 4095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (is_retransmission) 4105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 4115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Get the old control word and clear out the old req_seq and F bits */ 412d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen p = ((uint8_t *) (p_buf+1)) + p_buf->offset + L2CAP_PKT_OVERHEAD; 4135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 4145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project STREAM_TO_UINT16 (ctrl_word, p); 4155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 4165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ctrl_word &= ~(L2CAP_FCR_REQ_SEQ_BITS + L2CAP_FCR_F_BIT); 4175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 4185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project else 4195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 4205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ctrl_word = p_buf->layer_specific & L2CAP_FCR_SEG_BITS; /* SAR bits */ 4215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ctrl_word |= (p_fcrb->next_tx_seq << L2CAP_FCR_TX_SEQ_BITS_SHIFT); /* Tx Seq */ 4225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 4235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_fcrb->next_tx_seq = (p_fcrb->next_tx_seq + 1) & L2CAP_FCR_SEQ_MODULO; 4245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 4255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 4265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Set the F-bit and reqseq only if using re-transmission mode */ 4275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) 4285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 4295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (set_f_bit) 4305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ctrl_word |= L2CAP_FCR_F_BIT; 4315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 4325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ctrl_word |= (p_fcrb->next_seq_expected) << L2CAP_FCR_REQ_SEQ_BITS_SHIFT; 4335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 4345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_fcrb->last_ack_sent = p_ccb->fcrb.next_seq_expected; 4355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 43678bcff79e1b1f0efce436b33bdd6da88745bfc8aPavlin Radoslavov alarm_cancel(p_ccb->fcrb.ack_timer); 4375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 4385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 4395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Set the control word */ 440d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen p = ((uint8_t *) (p_buf+1)) + p_buf->offset + L2CAP_PKT_OVERHEAD; 4415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 4425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project UINT16_TO_STREAM (p, ctrl_word); 4435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 4445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Compute the FCS and add to the end of the buffer if not bypassed */ 4455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (p_ccb->bypass_fcs != L2CAP_BYPASS_FCS) 4465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 4475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* length field in l2cap header has to include FCS length */ 448d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen p = ((uint8_t *) (p_buf+1)) + p_buf->offset; 4495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project UINT16_TO_STREAM (p, p_buf->len + L2CAP_FCS_LEN - L2CAP_PKT_OVERHEAD); 4505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 4515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Calculate the FCS */ 4525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project fcs = l2c_fcr_tx_get_fcs(p_buf); 4535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 4545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Point to the end of the buffer and put the FCS there */ 455871e9ba3063530a81ca7ff03e8433c25e1e8c096Pavlin Radoslavov /* 456871e9ba3063530a81ca7ff03e8433c25e1e8c096Pavlin Radoslavov * NOTE: Here we assume the allocated buffer is large enough 457871e9ba3063530a81ca7ff03e8433c25e1e8c096Pavlin Radoslavov * to include extra L2CAP_FCS_LEN octets at the end. 458871e9ba3063530a81ca7ff03e8433c25e1e8c096Pavlin Radoslavov */ 459d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen p = ((uint8_t *) (p_buf+1)) + p_buf->offset + p_buf->len; 4605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 4615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project UINT16_TO_STREAM (p, fcs); 4625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 4635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_buf->len += L2CAP_FCS_LEN; 4645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 4655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 4665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (is_retransmission) 4675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 468a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati L2CAP_TRACE_EVENT ("L2CAP eRTM ReTx I-frame CID: 0x%04x Len: %u SAR: %s TxSeq: %u ReqSeq: %u F: %u", 4695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->local_cid, p_buf->len, 4705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project SAR_types[(ctrl_word & L2CAP_FCR_SAR_BITS) >> L2CAP_FCR_SAR_BITS_SHIFT], 4715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project (ctrl_word & L2CAP_FCR_TX_SEQ_BITS) >> L2CAP_FCR_TX_SEQ_BITS_SHIFT, 4725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project (ctrl_word & L2CAP_FCR_REQ_SEQ_BITS) >> L2CAP_FCR_REQ_SEQ_BITS_SHIFT, 4735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project (ctrl_word & L2CAP_FCR_F_BIT) >> L2CAP_FCR_F_BIT_SHIFT); 4745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 4755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project else 4765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 477a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati L2CAP_TRACE_EVENT ("L2CAP eRTM Tx I-frame CID: 0x%04x Len: %u SAR: %-12s TxSeq: %u ReqSeq: %u F: %u", 4785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->local_cid, p_buf->len, 4795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project SAR_types[(ctrl_word & L2CAP_FCR_SAR_BITS) >> L2CAP_FCR_SAR_BITS_SHIFT], 4805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project (ctrl_word & L2CAP_FCR_TX_SEQ_BITS) >> L2CAP_FCR_TX_SEQ_BITS_SHIFT, 4815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project (ctrl_word & L2CAP_FCR_REQ_SEQ_BITS) >> L2CAP_FCR_REQ_SEQ_BITS_SHIFT, 4825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project (ctrl_word & L2CAP_FCR_F_BIT) >> L2CAP_FCR_F_BIT_SHIFT); 4835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 4845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 4855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Start the retransmission timer if not already running */ 4865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) 4875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project l2c_fcr_start_timer (p_ccb); 4885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 4895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 4905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 491ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 492ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2c_fcr_send_S_frame 493ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 494ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description This function formats and sends an S-frame for transmission. 495ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 496ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns - 497ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 498ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 499d19e0785e662e640191a075eda07acce61c2aedaMarie Janssenvoid l2c_fcr_send_S_frame (tL2C_CCB *p_ccb, uint16_t function_code, uint16_t pf_bit) 5005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{ 501ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton assert(p_ccb != NULL); 502d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen uint8_t *p; 503d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen uint16_t ctrl_word; 504d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen uint16_t fcs; 5055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 5065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if ((!p_ccb->in_use) || (p_ccb->chnl_state != CST_OPEN)) 5075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project return; 5085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 5095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ERTM_STATS == TRUE) 5105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->fcrb.s_frames_sent[function_code]++; 5115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif 5125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 5135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (pf_bit == L2CAP_FCR_P_BIT) 5145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 515d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen p_ccb->fcrb.wait_ack = true; 5165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 5175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project l2c_fcr_stop_timer (p_ccb); /* Restart the monitor timer */ 5185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project l2c_fcr_start_timer (p_ccb); 5195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 5205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 5215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Create the control word to use */ 5225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ctrl_word = (function_code << L2CAP_FCR_SUP_SHIFT) | L2CAP_FCR_S_FRAME_BIT; 5235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ctrl_word |= (p_ccb->fcrb.next_seq_expected << L2CAP_FCR_REQ_SEQ_BITS_SHIFT); 5245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ctrl_word |= pf_bit; 5255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 526717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov BT_HDR *p_buf = (BT_HDR *)osi_malloc(L2CAP_CMD_BUF_SIZE); 527717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov p_buf->offset = HCI_DATA_PREAMBLE_SIZE; 528717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov p_buf->len = L2CAP_PKT_OVERHEAD + L2CAP_FCR_OVERHEAD; 5295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 530717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov /* Set the pointer to the beginning of the data */ 531d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen p = (uint8_t *)(p_buf + 1) + p_buf->offset; 5325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 533717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov /* Put in the L2CAP header */ 534717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov UINT16_TO_STREAM(p, L2CAP_FCR_OVERHEAD + L2CAP_FCS_LEN); 535717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov UINT16_TO_STREAM(p, p_ccb->remote_cid); 536717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov UINT16_TO_STREAM(p, ctrl_word); 5375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 538717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov /* Compute the FCS and add to the end of the buffer if not bypassed */ 539717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov if (p_ccb->bypass_fcs != L2CAP_BYPASS_FCS) { 540717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov fcs = l2c_fcr_tx_get_fcs (p_buf); 5415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 542717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov UINT16_TO_STREAM (p, fcs); 543717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov p_buf->len += L2CAP_FCS_LEN; 544717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov } else { 545717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov /* rewrite the length without FCS length */ 546717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov p -= 6; 547717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov UINT16_TO_STREAM (p, L2CAP_FCR_OVERHEAD); 548717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov } 5495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 550717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov /* Now, the HCI transport header */ 551717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov p_buf->layer_specific = L2CAP_NON_FLUSHABLE_PKT; 552717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov l2cu_set_acl_hci_header (p_buf, p_ccb); 5535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 554717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov if ((((ctrl_word & L2CAP_FCR_SUP_BITS) >> L2CAP_FCR_SUP_SHIFT) == 1) 555717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov || (((ctrl_word & L2CAP_FCR_SUP_BITS) >> L2CAP_FCR_SUP_SHIFT) == 3)) { 556717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov L2CAP_TRACE_WARNING("L2CAP eRTM Tx S-frame CID: 0x%04x ctrlword: 0x%04x Type: %s ReqSeq: %u P: %u F: %u", 5575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->local_cid, ctrl_word, 5585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project SUP_types[(ctrl_word & L2CAP_FCR_SUP_BITS) >> L2CAP_FCR_SUP_SHIFT], 5595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project (ctrl_word & L2CAP_FCR_REQ_SEQ_BITS) >> L2CAP_FCR_REQ_SEQ_BITS_SHIFT, 5605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project (ctrl_word & L2CAP_FCR_P_BIT) >> L2CAP_FCR_P_BIT_SHIFT, 5615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project (ctrl_word & L2CAP_FCR_F_BIT) >> L2CAP_FCR_F_BIT_SHIFT); 562717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov L2CAP_TRACE_WARNING (" Buf Len: %u", p_buf->len); 563717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov } else { 564717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov L2CAP_TRACE_EVENT("L2CAP eRTM Tx S-frame CID: 0x%04x ctrlword: 0x%04x Type: %s ReqSeq: %u P: %u F: %u", 565717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov p_ccb->local_cid, ctrl_word, 566717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov SUP_types[(ctrl_word & L2CAP_FCR_SUP_BITS) >> L2CAP_FCR_SUP_SHIFT], 567717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov (ctrl_word & L2CAP_FCR_REQ_SEQ_BITS) >> L2CAP_FCR_REQ_SEQ_BITS_SHIFT, 568717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov (ctrl_word & L2CAP_FCR_P_BIT) >> L2CAP_FCR_P_BIT_SHIFT, 569717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov (ctrl_word & L2CAP_FCR_F_BIT) >> L2CAP_FCR_F_BIT_SHIFT); 570717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov L2CAP_TRACE_EVENT(" Buf Len: %u", p_buf->len); 571717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov } 5725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 573717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, p_buf); 5745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 575717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov p_ccb->fcrb.last_ack_sent = p_ccb->fcrb.next_seq_expected; 5765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 577717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov alarm_cancel(p_ccb->fcrb.ack_timer); 5785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 5795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 5805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 5815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 582ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 583ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2c_fcr_proc_pdu 584ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 585ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description This function is the entry point for processing of a 5869ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * received PDU when in flow control and/or retransmission 5879ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * modes. 588ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 589ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns - 590ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 591ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 5925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectvoid l2c_fcr_proc_pdu (tL2C_CCB *p_ccb, BT_HDR *p_buf) 5935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{ 594ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton assert(p_ccb != NULL); 595ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton assert(p_buf != NULL); 596d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen uint8_t *p; 597d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen uint16_t fcs; 598d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen uint16_t min_pdu_len; 599d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen uint16_t ctrl_word; 6005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 6015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Check the length */ 6025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project min_pdu_len = (p_ccb->bypass_fcs == L2CAP_BYPASS_FCS) ? 603d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen (uint16_t)L2CAP_FCR_OVERHEAD : (uint16_t)(L2CAP_FCS_LEN + L2CAP_FCR_OVERHEAD); 6045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 6055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (p_buf->len < min_pdu_len) 6065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 607a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati L2CAP_TRACE_WARNING ("Rx L2CAP PDU: CID: 0x%04x Len too short: %u", p_ccb->local_cid, p_buf->len); 608cceb430489a70add1b996d54289867c17f4ac0fdPavlin Radoslavov osi_free(p_buf); 6095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project return; 6105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 6115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 6125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_STREAM_MODE) 6135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 6145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project process_stream_frame (p_ccb, p_buf); 6155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project return; 6165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 6175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 6185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Get the control word */ 619d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen p = ((uint8_t *)(p_buf+1)) + p_buf->offset; 6205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project STREAM_TO_UINT16 (ctrl_word, p); 6215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 6225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (ctrl_word & L2CAP_FCR_S_FRAME_BIT) 6235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 6245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if ((((ctrl_word & L2CAP_FCR_SUP_BITS) >> L2CAP_FCR_SUP_SHIFT) == 1) 6255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project || (((ctrl_word & L2CAP_FCR_SUP_BITS) >> L2CAP_FCR_SUP_SHIFT) == 3)) 6265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 6275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* REJ or SREJ */ 628a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati L2CAP_TRACE_WARNING ("L2CAP eRTM Rx S-frame: cid: 0x%04x Len: %u Type: %s ReqSeq: %u P: %u F: %u", 6295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->local_cid, p_buf->len, 6305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project SUP_types[(ctrl_word & L2CAP_FCR_SUP_BITS) >> L2CAP_FCR_SUP_SHIFT], 6315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project (ctrl_word & L2CAP_FCR_REQ_SEQ_BITS) >> L2CAP_FCR_REQ_SEQ_BITS_SHIFT, 6325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project (ctrl_word & L2CAP_FCR_P_BIT) >> L2CAP_FCR_P_BIT_SHIFT, 6335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project (ctrl_word & L2CAP_FCR_F_BIT) >> L2CAP_FCR_F_BIT_SHIFT); 6345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 6355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project else 6365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 637a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati L2CAP_TRACE_EVENT ("L2CAP eRTM Rx S-frame: cid: 0x%04x Len: %u Type: %s ReqSeq: %u P: %u F: %u", 6385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->local_cid, p_buf->len, 6395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project SUP_types[(ctrl_word & L2CAP_FCR_SUP_BITS) >> L2CAP_FCR_SUP_SHIFT], 6405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project (ctrl_word & L2CAP_FCR_REQ_SEQ_BITS) >> L2CAP_FCR_REQ_SEQ_BITS_SHIFT, 6415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project (ctrl_word & L2CAP_FCR_P_BIT) >> L2CAP_FCR_P_BIT_SHIFT, 6425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project (ctrl_word & L2CAP_FCR_F_BIT) >> L2CAP_FCR_F_BIT_SHIFT); 6435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 6445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 6455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project else 6465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 647a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati L2CAP_TRACE_EVENT ("L2CAP eRTM Rx I-frame: cid: 0x%04x Len: %u SAR: %-12s TxSeq: %u ReqSeq: %u F: %u", 6485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->local_cid, p_buf->len, 6495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project SAR_types[(ctrl_word & L2CAP_FCR_SAR_BITS) >> L2CAP_FCR_SAR_BITS_SHIFT], 6505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project (ctrl_word & L2CAP_FCR_TX_SEQ_BITS) >> L2CAP_FCR_TX_SEQ_BITS_SHIFT, 6515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project (ctrl_word & L2CAP_FCR_REQ_SEQ_BITS) >> L2CAP_FCR_REQ_SEQ_BITS_SHIFT, 6525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project (ctrl_word & L2CAP_FCR_F_BIT) >> L2CAP_FCR_F_BIT_SHIFT); 6535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 6545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 655a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati L2CAP_TRACE_EVENT (" eRTM Rx Nxt_tx_seq %u, Lst_rx_ack %u, Nxt_seq_exp %u, Lst_ack_snt %u, wt_q.cnt %u, tries %u", 6561a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov p_ccb->fcrb.next_tx_seq, p_ccb->fcrb.last_rx_ack, 6571a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov p_ccb->fcrb.next_seq_expected, 6581a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov p_ccb->fcrb.last_ack_sent, 6591a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov fixed_queue_length(p_ccb->fcrb.waiting_for_ack_q), 6601a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov p_ccb->fcrb.num_tries); 6615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 6625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Verify FCS if using */ 6635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (p_ccb->bypass_fcs != L2CAP_BYPASS_FCS) 6645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 665d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen p = ((uint8_t *)(p_buf+1)) + p_buf->offset + p_buf->len - L2CAP_FCS_LEN; 6665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 6675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Extract and drop the FCS from the packet */ 6685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project STREAM_TO_UINT16 (fcs, p); 6695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_buf->len -= L2CAP_FCS_LEN; 6705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 6715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (l2c_fcr_rx_get_fcs(p_buf) != fcs) 6725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 673a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati L2CAP_TRACE_WARNING ("Rx L2CAP PDU: CID: 0x%04x BAD FCS", p_ccb->local_cid); 674cceb430489a70add1b996d54289867c17f4ac0fdPavlin Radoslavov osi_free(p_buf); 6755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project return; 6765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 6775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 6785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 6795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Get the control word */ 680d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen p = ((uint8_t *)(p_buf+1)) + p_buf->offset; 6815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 6825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project STREAM_TO_UINT16 (ctrl_word, p); 6835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 6845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_buf->len -= L2CAP_FCR_OVERHEAD; 6855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_buf->offset += L2CAP_FCR_OVERHEAD; 6865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 6875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* If we had a poll bit outstanding, check if we got a final response */ 6885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (p_ccb->fcrb.wait_ack) 6895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 6905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* If final bit not set, ignore the frame unless it is a polled S-frame */ 6915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if ( !(ctrl_word & L2CAP_FCR_F_BIT) ) 6925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 6935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if ( (ctrl_word & L2CAP_FCR_P_BIT) && (ctrl_word & L2CAP_FCR_S_FRAME_BIT) ) 6945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 6955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (p_ccb->fcrb.srej_sent) 6965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project l2c_fcr_send_S_frame (p_ccb, L2CAP_FCR_SUP_SREJ, L2CAP_FCR_F_BIT); 6975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project else if (p_ccb->fcrb.local_busy) 6985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project l2c_fcr_send_S_frame (p_ccb, L2CAP_FCR_SUP_RNR, L2CAP_FCR_F_BIT); 6995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project else 7005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project l2c_fcr_send_S_frame (p_ccb, L2CAP_FCR_SUP_RR, L2CAP_FCR_F_BIT); 7015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 7025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Got a poll while in wait_ack state, so re-start our timer with 1-second */ 7035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* This is a small optimization... the monitor timer is 12 secs, but we saw */ 7045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* that if the other side sends us a poll when we are waiting for a final, */ 7055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* then it speeds up recovery significantly if we poll him back soon after his poll. */ 70678bcff79e1b1f0efce436b33bdd6da88745bfc8aPavlin Radoslavov alarm_set_on_queue(p_ccb->fcrb.mon_retrans_timer, 70778bcff79e1b1f0efce436b33bdd6da88745bfc8aPavlin Radoslavov BT_1SEC_TIMEOUT_MS, 70878bcff79e1b1f0efce436b33bdd6da88745bfc8aPavlin Radoslavov l2c_ccb_timer_timeout, p_ccb, 70978bcff79e1b1f0efce436b33bdd6da88745bfc8aPavlin Radoslavov btu_general_alarm_queue); 7105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 711cceb430489a70add1b996d54289867c17f4ac0fdPavlin Radoslavov osi_free(p_buf); 7125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project return; 7135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 7145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 715d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen p_ccb->fcrb.wait_ack = false; 7165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 7175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* P and F are mutually exclusive */ 7185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (ctrl_word & L2CAP_FCR_S_FRAME_BIT) 7195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ctrl_word &= ~L2CAP_FCR_P_BIT; 7205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 7211a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov if (fixed_queue_is_empty(p_ccb->fcrb.waiting_for_ack_q)) 7225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->fcrb.num_tries = 0; 7235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 7245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project l2c_fcr_stop_timer (p_ccb); 7255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 7265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project else 7275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 7285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Otherwise, ensure the final bit is ignored */ 7295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ctrl_word &= ~L2CAP_FCR_F_BIT; 7305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 7315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 7325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Process receive sequence number */ 7335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (!process_reqseq (p_ccb, ctrl_word)) 7345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 735cceb430489a70add1b996d54289867c17f4ac0fdPavlin Radoslavov osi_free(p_buf); 7365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project return; 7375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 7385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 7395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Process based on whether it is an S-frame or an I-frame */ 7405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (ctrl_word & L2CAP_FCR_S_FRAME_BIT) 7415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project process_s_frame (p_ccb, p_buf, ctrl_word); 7425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project else 743d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen process_i_frame (p_ccb, p_buf, ctrl_word, false); 7445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 7455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Return if the channel got disconnected by a bad packet or max retransmissions */ 7465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if ( (!p_ccb->in_use) || (p_ccb->chnl_state != CST_OPEN) ) 7475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project return; 7485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 7495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* If we have some buffers held while doing SREJ, and SREJ has cleared, process them now */ 7501a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov if ( (!p_ccb->fcrb.local_busy) && (!p_ccb->fcrb.srej_sent) && 7511a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov (!fixed_queue_is_empty(p_ccb->fcrb.srej_rcv_hold_q))) 7525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 7531a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov fixed_queue_t *temp_q = p_ccb->fcrb.srej_rcv_hold_q; 7541a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov p_ccb->fcrb.srej_rcv_hold_q = fixed_queue_new(SIZE_MAX); 7555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 7561a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov while ((p_buf = (BT_HDR *)fixed_queue_try_dequeue(temp_q)) != NULL) 7575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 7585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (p_ccb->in_use && (p_ccb->chnl_state == CST_OPEN)) 7595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 7605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Get the control word */ 761d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen p = ((uint8_t *)(p_buf+1)) + p_buf->offset - L2CAP_FCR_OVERHEAD; 7625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 7635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project STREAM_TO_UINT16 (ctrl_word, p); 7645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 765a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati L2CAP_TRACE_DEBUG ("l2c_fcr_proc_pdu() CID: 0x%04x Process Buffer from SREJ_Hold_Q TxSeq: %u Expected_Seq: %u", 7665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->local_cid, (ctrl_word & L2CAP_FCR_TX_SEQ_BITS) >> L2CAP_FCR_TX_SEQ_BITS_SHIFT, 7675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->fcrb.next_seq_expected); 7685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 7695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Process the SREJ held I-frame, but do not send an RR for each individual frame */ 770d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen process_i_frame (p_ccb, p_buf, ctrl_word, true); 7715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 7725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project else 773cceb430489a70add1b996d54289867c17f4ac0fdPavlin Radoslavov osi_free(p_buf); 7745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 7755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* If more frames were lost during SREJ, send a REJ */ 7765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (p_ccb->fcrb.rej_after_srej) 7775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 778d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen p_ccb->fcrb.rej_after_srej = false; 779d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen p_ccb->fcrb.rej_sent = true; 7805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 7815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project l2c_fcr_send_S_frame (p_ccb, L2CAP_FCR_SUP_REJ, 0); 7825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 7835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 7841a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov fixed_queue_free(temp_q, NULL); 7855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 7865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Now, if needed, send one RR for the whole held queue */ 7875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if ( (!p_ccb->fcrb.local_busy) && (!p_ccb->fcrb.rej_sent) && (!p_ccb->fcrb.srej_sent) 7885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project && (p_ccb->fcrb.next_seq_expected != p_ccb->fcrb.last_ack_sent) ) 7895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project l2c_fcr_send_S_frame (p_ccb, L2CAP_FCR_SUP_RR, 0); 7905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project else 7915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 792a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati L2CAP_TRACE_DEBUG ("l2c_fcr_proc_pdu() not sending RR CID: 0x%04x local_busy:%d rej_sent:%d srej_sent:%d Expected_Seq:%u Last_Ack:%u", 7935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->local_cid, p_ccb->fcrb.local_busy, p_ccb->fcrb.rej_sent, p_ccb->fcrb.srej_sent, p_ccb->fcrb.next_seq_expected, 7945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->fcrb.last_ack_sent); 7955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 7965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 7975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 7985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* If a window has opened, check if we can send any more packets */ 7991a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov if ( (!fixed_queue_is_empty(p_ccb->fcrb.retrans_q) || 8001a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov !fixed_queue_is_empty(p_ccb->xmit_hold_q)) 801d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen && (p_ccb->fcrb.wait_ack == false) 802d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen && (l2c_fcr_is_flow_controlled (p_ccb) == false) ) 8035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 8045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, NULL); 8055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 8065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 8075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 8085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 809ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 810ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2c_lcc_proc_pdu 811ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 812ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description This function is the entry point for processing of a 813ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * received PDU when in LE Coc flow control modes. 814ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 815ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns - 816ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 817ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 8186721232129f137ab024d9b95fc1094a714bc4c01Navin Kocharvoid l2c_lcc_proc_pdu(tL2C_CCB *p_ccb, BT_HDR *p_buf) 8196721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar{ 8206721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 8216721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar assert(p_ccb != NULL); 8226721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar assert(p_buf != NULL); 823d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen uint8_t *p = (uint8_t*)(p_buf + 1) + p_buf->offset; 824d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen uint16_t sdu_length; 8256721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar BT_HDR *p_data = NULL; 8266721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 8276721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar /* Buffer length should not exceed local mps */ 8286721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar if (p_buf->len > p_ccb->local_conn_cfg.mps) 8296721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar { 8306721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar /* Discard the buffer */ 8316721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar osi_free(p_buf); 8326721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar return; 8336721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar } 8346721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 8356721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar if (p_ccb->is_first_seg) 8366721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar { 8376721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar STREAM_TO_UINT16(sdu_length, p); 8386721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar /* Check the SDU Length with local MTU size */ 8396721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar if (sdu_length > p_ccb->local_conn_cfg.mtu) 8406721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar { 8416721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar /* Discard the buffer */ 8426721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar osi_free(p_buf); 8436721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar return; 8446721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar } 8456721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 8466721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 847f33b6f434f086b20fabe5913016bc423ac975057Marie Janssen p_data = (BT_HDR *)osi_malloc(L2CAP_MAX_BUF_SIZE); 848f33b6f434f086b20fabe5913016bc423ac975057Marie Janssen if (p_data == NULL) 8496721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar { 8506721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar osi_free(p_buf); 8516721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar return; 8526721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar } 8536721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 8546721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar p_ccb->ble_sdu = p_data; 8556721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar p_data->len = 0; 8566721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar p_ccb->ble_sdu_length = sdu_length; 8576721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar L2CAP_TRACE_DEBUG ("%s SDU Length = %d",__func__,sdu_length); 8586721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar p_buf->len -= sizeof(sdu_length); 8596721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar p_buf->offset += sizeof(sdu_length); 8606721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar p_data->offset = 0; 8616721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 8626721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar } 8636721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar else 8646721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar p_data = p_ccb->ble_sdu; 8656721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 866d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen memcpy((uint8_t*)(p_data + 1) + p_data->offset + p_data->len, (uint8_t*)(p_buf + 1) + p_buf->offset, p_buf->len); 8676721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar p_data->len += p_buf->len; 868d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen p = (uint8_t*)(p_data+1) + p_data->offset; 8696721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar if (p_data->len == p_ccb->ble_sdu_length) 8706721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar { 8716721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar l2c_csm_execute (p_ccb, L2CEVT_L2CAP_DATA, p_data); 872d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen p_ccb->is_first_seg = true; 8736721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar p_ccb->ble_sdu = NULL; 8746721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar p_ccb->ble_sdu_length = 0; 8756721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar } 8766721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar else if (p_data->len < p_ccb->ble_sdu_length) 8776721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar { 878d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen p_ccb->is_first_seg = false; 8796721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar } 8806721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar else 8816721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar { 8826721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar L2CAP_TRACE_ERROR ("%s Length in the SDU messed up",__func__); 8836721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar // TODO: reset every thing may be??? 8846721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar } 8856721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 8866721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar osi_free(p_buf); 8876721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar return; 8886721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar} 8896721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 8906721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar/******************************************************************************* 891ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 892ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2c_fcr_proc_tout 893ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 894ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Handle a timeout. We should be in error recovery state. 895ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 896ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns - 897ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 898ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 8995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectvoid l2c_fcr_proc_tout (tL2C_CCB *p_ccb) 9005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{ 901ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton assert(p_ccb != NULL); 902a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati L2CAP_TRACE_DEBUG ("l2c_fcr_proc_tout: CID: 0x%04x num_tries: %u (max: %u) wait_ack: %u ack_q_count: %u", 9031a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov p_ccb->local_cid, p_ccb->fcrb.num_tries, 9041a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov p_ccb->peer_cfg.fcr.max_transmit, 9051a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov p_ccb->fcrb.wait_ack, 9061a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov fixed_queue_length(p_ccb->fcrb.waiting_for_ack_q)); 9075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 9085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ERTM_STATS == TRUE) 9095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->fcrb.retrans_touts++; 9105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif 9115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 9125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if ( (p_ccb->peer_cfg.fcr.max_transmit != 0) && (++p_ccb->fcrb.num_tries > p_ccb->peer_cfg.fcr.max_transmit) ) 9135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 9145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project l2cu_disconnect_chnl (p_ccb); 9155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 9165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project else 9175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 9185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (!p_ccb->fcrb.srej_sent && !p_ccb->fcrb.rej_sent) 9195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 9205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (p_ccb->fcrb.local_busy) 9215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project l2c_fcr_send_S_frame (p_ccb, L2CAP_FCR_SUP_RNR, L2CAP_FCR_P_BIT); 9225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project else 9235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project l2c_fcr_send_S_frame (p_ccb, L2CAP_FCR_SUP_RR, L2CAP_FCR_P_BIT); 9245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 9255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 9265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 9275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 9285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 9295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 930ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 931ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2c_fcr_proc_ack_tout 932ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 933ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Send RR/RNR if we have not acked I frame 934ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 935ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns - 936ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 937ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 9385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectvoid l2c_fcr_proc_ack_tout (tL2C_CCB *p_ccb) 9395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{ 940ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton assert(p_ccb != NULL); 941a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati L2CAP_TRACE_DEBUG ("l2c_fcr_proc_ack_tout: CID: 0x%04x State: %u Wack:%u Rq:%d Acked:%d", p_ccb->local_cid, 9425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->chnl_state, p_ccb->fcrb.wait_ack, p_ccb->fcrb.next_seq_expected, p_ccb->fcrb.last_ack_sent); 9435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 9445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if ( (p_ccb->chnl_state == CST_OPEN) && (!p_ccb->fcrb.wait_ack) 9455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project && (p_ccb->fcrb.last_ack_sent != p_ccb->fcrb.next_seq_expected) ) 9465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 9475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ERTM_STATS == TRUE) 9485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->fcrb.xmit_ack_touts++; 9495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif 9505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (p_ccb->fcrb.local_busy) 9515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project l2c_fcr_send_S_frame (p_ccb, L2CAP_FCR_SUP_RNR, 0); 9525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project else 9535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project l2c_fcr_send_S_frame (p_ccb, L2CAP_FCR_SUP_RR, 0); 9545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 9555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 9565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 9575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 9585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 959ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 960ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function process_reqseq 961ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 962ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Handle receive sequence number 963ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 964ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns - 965ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 966ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 967d19e0785e662e640191a075eda07acce61c2aedaMarie Janssenstatic bool process_reqseq (tL2C_CCB *p_ccb, uint16_t ctrl_word) 9685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{ 969ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton assert(p_ccb != NULL); 9705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project tL2C_FCRB *p_fcrb = &p_ccb->fcrb; 971d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen uint8_t req_seq, num_bufs_acked, xx; 972d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen uint16_t ls; 973d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen uint16_t full_sdus_xmitted; 9745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 9755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Receive sequence number does not ack anything for SREJ with P-bit set to zero */ 9765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if ( (ctrl_word & L2CAP_FCR_S_FRAME_BIT) 9775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project && ((ctrl_word & L2CAP_FCR_SUP_BITS) == (L2CAP_FCR_SUP_SREJ << L2CAP_FCR_SUP_SHIFT)) 9785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project && ((ctrl_word & L2CAP_FCR_P_BIT) == 0) ) 9795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 9805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* If anything still waiting for ack, restart the timer if it was stopped */ 9811a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov if (!fixed_queue_is_empty(p_fcrb->waiting_for_ack_q)) 9821a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov l2c_fcr_start_timer(p_ccb); 9835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 984d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen return (true); 9855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 9865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 9875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Extract the receive sequence number from the control word */ 9885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project req_seq = (ctrl_word & L2CAP_FCR_REQ_SEQ_BITS) >> L2CAP_FCR_REQ_SEQ_BITS_SHIFT; 9895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 9905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project num_bufs_acked = (req_seq - p_fcrb->last_rx_ack) & L2CAP_FCR_SEQ_MODULO; 9915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 9925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Verify the request sequence is in range before proceeding */ 9931a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov if (num_bufs_acked > fixed_queue_length(p_fcrb->waiting_for_ack_q)) 9945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 9955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* The channel is closed if ReqSeq is not in range */ 996a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati L2CAP_TRACE_WARNING ("L2CAP eRTM Frame BAD Req_Seq - ctrl_word: 0x%04x req_seq 0x%02x last_rx_ack: 0x%02x QCount: %u", 9971a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov ctrl_word, req_seq, p_fcrb->last_rx_ack, 9981a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov fixed_queue_length(p_fcrb->waiting_for_ack_q)); 9995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 10005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project l2cu_disconnect_chnl (p_ccb); 1001d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen return (false); 10025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 10035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 10045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_fcrb->last_rx_ack = req_seq; 10055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 10065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Now we can release all acknowledged frames, and restart the retransmission timer if needed */ 10075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (num_bufs_acked != 0) 10085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 10095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_fcrb->num_tries = 0; 10105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project full_sdus_xmitted = 0; 10115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 10125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ERTM_STATS == TRUE) 10135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project l2c_fcr_collect_ack_delay (p_ccb, num_bufs_acked); 10145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif 10155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 10165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project for (xx = 0; xx < num_bufs_acked; xx++) 10175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 10181a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov BT_HDR *p_tmp = (BT_HDR *)fixed_queue_try_dequeue(p_fcrb->waiting_for_ack_q); 10191a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov ls = p_tmp->layer_specific & L2CAP_FCR_SAR_BITS; 10205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 10215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if ( (ls == L2CAP_FCR_UNSEG_SDU) || (ls == L2CAP_FCR_END_SDU) ) 10225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project full_sdus_xmitted++; 10235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1024cceb430489a70add1b996d54289867c17f4ac0fdPavlin Radoslavov osi_free(p_tmp); 10255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 10265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 10275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* If we are still in a wait_ack state, do not mess with the timer */ 10285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (!p_ccb->fcrb.wait_ack) 10295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project l2c_fcr_stop_timer (p_ccb); 10305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 10315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Check if we need to call the "packet_sent" callback */ 10325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if ( (p_ccb->p_rcb) && (p_ccb->p_rcb->api.pL2CA_TxComplete_Cb) && (full_sdus_xmitted) ) 10335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 10345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Special case for eRTM, if all packets sent, send 0xFFFF */ 10351a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov if (fixed_queue_is_empty(p_fcrb->waiting_for_ack_q) && 10361a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov fixed_queue_is_empty(p_ccb->xmit_hold_q)) { 10375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project full_sdus_xmitted = 0xFFFF; 10381a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov } 10395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 10405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project (*p_ccb->p_rcb->api.pL2CA_TxComplete_Cb)(p_ccb->local_cid, full_sdus_xmitted); 10415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 10425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 10435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 10445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* If anything still waiting for ack, restart the timer if it was stopped */ 10451a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov if (!fixed_queue_is_empty(p_fcrb->waiting_for_ack_q)) 10461a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov l2c_fcr_start_timer(p_ccb); 1047d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen return (true); 10485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 10495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 10505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 10515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 1052ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1053ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function process_s_frame 1054ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1055ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Process an S frame 1056ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1057ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns - 1058ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1059ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 1060d19e0785e662e640191a075eda07acce61c2aedaMarie Janssenstatic void process_s_frame (tL2C_CCB *p_ccb, BT_HDR *p_buf, uint16_t ctrl_word) 10615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{ 1062ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton assert(p_ccb != NULL); 1063ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton assert(p_buf != NULL); 1064ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton 10655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project tL2C_FCRB *p_fcrb = &p_ccb->fcrb; 1066d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen uint16_t s_frame_type = (ctrl_word & L2CAP_FCR_SUP_BITS) >> L2CAP_FCR_SUP_SHIFT; 1067d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen bool remote_was_busy; 1068d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen bool all_ok = true; 10695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 10705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (p_buf->len != 0) 10715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 1072a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati L2CAP_TRACE_WARNING ("Incorrect S-frame Length (%d)", p_buf->len); 10735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 10745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1075a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati L2CAP_TRACE_DEBUG ("process_s_frame ctrl_word 0x%04x fcrb_remote_busy:%d", ctrl_word, p_fcrb->remote_busy); 10765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 10775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ERTM_STATS == TRUE) 10785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->fcrb.s_frames_rcvd[s_frame_type]++; 10795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif 10805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 10815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (ctrl_word & L2CAP_FCR_P_BIT) 10825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 1083d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen p_fcrb->rej_sent = false; /* After checkpoint, we can send anoher REJ */ 1084d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen p_fcrb->send_f_rsp = true; /* Set a flag in case an I-frame is pending */ 10855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 10865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 10875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project switch (s_frame_type) 10885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 10895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project case L2CAP_FCR_SUP_RR: 10905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project remote_was_busy = p_fcrb->remote_busy; 1091d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen p_fcrb->remote_busy = false; 10925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 10935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if ( (ctrl_word & L2CAP_FCR_F_BIT) || (remote_was_busy) ) 10945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project all_ok = retransmit_i_frames (p_ccb, L2C_FCR_RETX_ALL_PKTS); 10955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project break; 10965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 10975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project case L2CAP_FCR_SUP_REJ: 1098d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen p_fcrb->remote_busy = false; 10995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project all_ok = retransmit_i_frames (p_ccb, L2C_FCR_RETX_ALL_PKTS); 11005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project break; 11015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 11025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project case L2CAP_FCR_SUP_RNR: 1103d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen p_fcrb->remote_busy = true; 11045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project l2c_fcr_stop_timer (p_ccb); 11055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project break; 11065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 11075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project case L2CAP_FCR_SUP_SREJ: 1108d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen p_fcrb->remote_busy = false; 1109d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen all_ok = retransmit_i_frames (p_ccb, (uint8_t)((ctrl_word & L2CAP_FCR_REQ_SEQ_BITS) >> L2CAP_FCR_REQ_SEQ_BITS_SHIFT)); 11105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project break; 11115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 11125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 11135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (all_ok) 11145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 11155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* If polled, we need to respond with F-bit. Note, we may have sent a I-frame with the F-bit */ 11165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (p_fcrb->send_f_rsp) 11175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 11185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (p_fcrb->srej_sent) 11195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project l2c_fcr_send_S_frame (p_ccb, L2CAP_FCR_SUP_SREJ, L2CAP_FCR_F_BIT); 11205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project else if (p_fcrb->local_busy) 11215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project l2c_fcr_send_S_frame (p_ccb, L2CAP_FCR_SUP_RNR, L2CAP_FCR_F_BIT); 11225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project else 11235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project l2c_fcr_send_S_frame (p_ccb, L2CAP_FCR_SUP_RR, L2CAP_FCR_F_BIT); 11245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1125d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen p_fcrb->send_f_rsp = false; 11265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 11275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 11285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project else 11295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 1130a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati L2CAP_TRACE_DEBUG ("process_s_frame hit_max_retries"); 11315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 11325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1133cceb430489a70add1b996d54289867c17f4ac0fdPavlin Radoslavov osi_free(p_buf); 11345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 11355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 11365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 11375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 1138ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1139ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function process_i_frame 1140ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1141ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Process an I frame 1142ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1143ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns - 1144ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1145ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 1146d19e0785e662e640191a075eda07acce61c2aedaMarie Janssenstatic void process_i_frame (tL2C_CCB *p_ccb, BT_HDR *p_buf, uint16_t ctrl_word, bool delay_ack) 11475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{ 1148ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton assert(p_ccb != NULL); 1149ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton assert(p_buf != NULL); 1150ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton 11515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project tL2C_FCRB *p_fcrb = &p_ccb->fcrb; 1152d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen uint8_t tx_seq, num_lost, num_to_ack, next_srej; 11535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 11545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* If we were doing checkpoint recovery, first retransmit all unacked I-frames */ 11555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (ctrl_word & L2CAP_FCR_F_BIT) 11565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 11575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (!retransmit_i_frames (p_ccb, L2C_FCR_RETX_ALL_PKTS)) 11585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 1159cceb430489a70add1b996d54289867c17f4ac0fdPavlin Radoslavov osi_free(p_buf); 11605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project return; 11615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 11625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 11635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 11645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ERTM_STATS == TRUE) 11655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->fcrb.ertm_pkt_counts[1]++; 11665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->fcrb.ertm_byte_counts[1] += p_buf->len; 11675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif 11685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 11695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Extract the sequence number */ 11705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project tx_seq = (ctrl_word & L2CAP_FCR_TX_SEQ_BITS) >> L2CAP_FCR_TX_SEQ_BITS_SHIFT; 11715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 11725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* If we have flow controlled the peer, ignore any bad I-frames from him */ 11735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if ( (tx_seq != p_fcrb->next_seq_expected) && (p_fcrb->local_busy) ) 11745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 1175a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati L2CAP_TRACE_WARNING ("Dropping bad I-Frame since we flowed off, tx_seq:%u", tx_seq); 11765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project l2c_fcr_send_S_frame (p_ccb, L2CAP_FCR_SUP_RNR, 0); 1177cceb430489a70add1b996d54289867c17f4ac0fdPavlin Radoslavov osi_free(p_buf); 11785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project return; 11795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 11805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 11815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Check if tx-sequence is the expected one */ 11825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (tx_seq != p_fcrb->next_seq_expected) 11835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 11845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project num_lost = (tx_seq - p_fcrb->next_seq_expected) & L2CAP_FCR_SEQ_MODULO; 11855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 11865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Is the frame a duplicate ? If so, just drop it */ 11875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (num_lost >= p_ccb->our_cfg.fcr.tx_win_sz) 11885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 11895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Duplicate - simply drop it */ 1190a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati L2CAP_TRACE_WARNING ("process_i_frame() Dropping Duplicate Frame tx_seq:%u ExpectedTxSeq %u", tx_seq, p_fcrb->next_seq_expected); 1191cceb430489a70add1b996d54289867c17f4ac0fdPavlin Radoslavov osi_free(p_buf); 11925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 11935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project else 11945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 1195a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati L2CAP_TRACE_WARNING ("process_i_frame() CID: 0x%04x Lost: %u tx_seq:%u ExpTxSeq %u Rej: %u SRej: %u", 11965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->local_cid, num_lost, tx_seq, p_fcrb->next_seq_expected, p_fcrb->rej_sent, p_fcrb->srej_sent); 11975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 11985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (p_fcrb->srej_sent) 11995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 12005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* If SREJ sent, save the frame for later processing as long as it is in sequence */ 12011a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov next_srej = (((BT_HDR *)fixed_queue_try_peek_last(p_fcrb->srej_rcv_hold_q))->layer_specific + 1) & L2CAP_FCR_SEQ_MODULO; 12025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 12031a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov if ( (tx_seq == next_srej) && (fixed_queue_length(p_fcrb->srej_rcv_hold_q) < p_ccb->our_cfg.fcr.tx_win_sz) ) 12045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 12055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* If user gave us a pool for held rx buffers, use that */ 12061d5b85924df3a114efe6588e857d0de3eb47b1d2Pavlin Radoslavov /* TODO: Could that happen? Get rid of this code. */ 12071d5b85924df3a114efe6588e857d0de3eb47b1d2Pavlin Radoslavov if (p_ccb->ertm_info.fcr_rx_buf_size != L2CAP_FCR_RX_BUF_SIZE) 12085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 12095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project BT_HDR *p_buf2; 12105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 12115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Adjust offset and len so that control word is copied */ 12125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_buf->offset -= L2CAP_FCR_OVERHEAD; 12135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_buf->len += L2CAP_FCR_OVERHEAD; 12145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 12152e3d006b96eafb0651fe7f78d28250faf89405dePavlin Radoslavov p_buf2 = l2c_fcr_clone_buf(p_buf, p_buf->offset, p_buf->len); 12165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 12175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (p_buf2) 12185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 1219cceb430489a70add1b996d54289867c17f4ac0fdPavlin Radoslavov osi_free(p_buf); 12205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_buf = p_buf2; 12215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 12225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_buf->offset += L2CAP_FCR_OVERHEAD; 12235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_buf->len -= L2CAP_FCR_OVERHEAD; 12245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 1225a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati L2CAP_TRACE_DEBUG ("process_i_frame() Lost: %u tx_seq:%u ExpTxSeq %u Rej: %u SRej1", 12265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project num_lost, tx_seq, p_fcrb->next_seq_expected, p_fcrb->rej_sent); 12275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 12285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_buf->layer_specific = tx_seq; 12291a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov fixed_queue_enqueue(p_fcrb->srej_rcv_hold_q, p_buf); 12305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 12315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project else 12325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 1233a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati L2CAP_TRACE_WARNING ("process_i_frame() CID: 0x%04x frame dropped in Srej Sent next_srej:%u hold_q.count:%u win_sz:%u", 12341a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov p_ccb->local_cid, next_srej, fixed_queue_length(p_fcrb->srej_rcv_hold_q), p_ccb->our_cfg.fcr.tx_win_sz); 12355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1236d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen p_fcrb->rej_after_srej = true; 1237cceb430489a70add1b996d54289867c17f4ac0fdPavlin Radoslavov osi_free(p_buf); 12385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 12395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 12405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project else if (p_fcrb->rej_sent) 12415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 1242a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati L2CAP_TRACE_WARNING ("process_i_frame() CID: 0x%04x Lost: %u tx_seq:%u ExpTxSeq %u Rej: 1 SRej: %u", 12435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->local_cid, num_lost, tx_seq, p_fcrb->next_seq_expected, p_fcrb->srej_sent); 12445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 12455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* If REJ sent, just drop the frame */ 1246cceb430489a70add1b996d54289867c17f4ac0fdPavlin Radoslavov osi_free(p_buf); 12475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 12485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project else 12495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 1250a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati L2CAP_TRACE_DEBUG ("process_i_frame() CID: 0x%04x tx_seq:%u ExpTxSeq %u Rej: %u", 12515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->local_cid, tx_seq, p_fcrb->next_seq_expected, p_fcrb->rej_sent); 12525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 12535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* If only one lost, we will send SREJ, otherwise we will send REJ */ 12545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (num_lost > 1) 12555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 1256cceb430489a70add1b996d54289867c17f4ac0fdPavlin Radoslavov osi_free(p_buf); 1257d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen p_fcrb->rej_sent = true; 12585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project l2c_fcr_send_S_frame (p_ccb, L2CAP_FCR_SUP_REJ, 0); 12595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 12605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project else 12615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 12621a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov if (!fixed_queue_is_empty(p_fcrb->srej_rcv_hold_q)) 12635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 1264a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati L2CAP_TRACE_ERROR ("process_i_frame() CID: 0x%04x sending SREJ tx_seq:%d hold_q.count:%u", 12651a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov p_ccb->local_cid, tx_seq, fixed_queue_length(p_fcrb->srej_rcv_hold_q)); 12665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 12675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_buf->layer_specific = tx_seq; 12681a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov fixed_queue_enqueue(p_fcrb->srej_rcv_hold_q, p_buf); 1269d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen p_fcrb->srej_sent = true; 12705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project l2c_fcr_send_S_frame (p_ccb, L2CAP_FCR_SUP_SREJ, 0); 12715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 127278bcff79e1b1f0efce436b33bdd6da88745bfc8aPavlin Radoslavov alarm_cancel(p_ccb->fcrb.ack_timer); 12735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 12745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 12755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project return; 12765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 12775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 12785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Seq number is the next expected. Clear possible reject exception in case it occured */ 1279d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen p_fcrb->rej_sent = p_fcrb->srej_sent = false; 12805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 12815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Adjust the next_seq, so that if the upper layer sends more data in the callback 12825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project context, the received frame is acked by an I-frame. */ 12835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_fcrb->next_seq_expected = (tx_seq + 1) & L2CAP_FCR_SEQ_MODULO; 12845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 12855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* If any SAR problem in eRTM mode, spec says disconnect. */ 12865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (!do_sar_reassembly (p_ccb, p_buf, ctrl_word)) 12875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 1288a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati L2CAP_TRACE_WARNING ("process_i_frame() CID: 0x%04x reassembly failed", p_ccb->local_cid); 12895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project l2cu_disconnect_chnl (p_ccb); 12905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project return; 12915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 12925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 12935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* RR optimization - if peer can still send us more, then start an ACK timer */ 12945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project num_to_ack = (p_fcrb->next_seq_expected - p_fcrb->last_ack_sent) & L2CAP_FCR_SEQ_MODULO; 12955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 12965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if ( (num_to_ack < p_ccb->fcrb.max_held_acks) && (!p_fcrb->local_busy) ) 1297d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen delay_ack = true; 12985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 12995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* We should neve never ack frame if we are not in OPEN state */ 13005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if ((num_to_ack != 0) && p_ccb->in_use && (p_ccb->chnl_state == CST_OPEN)) 13015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 13025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* If no frames are awaiting transmission or are held, send an RR or RNR S-frame for ack */ 13035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (delay_ack) 13045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 13055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* If it is the first I frame we did not ack, start ack timer */ 130678bcff79e1b1f0efce436b33bdd6da88745bfc8aPavlin Radoslavov if (!alarm_is_scheduled(p_ccb->fcrb.ack_timer)) { 130778bcff79e1b1f0efce436b33bdd6da88745bfc8aPavlin Radoslavov alarm_set_on_queue(p_ccb->fcrb.ack_timer, 130878bcff79e1b1f0efce436b33bdd6da88745bfc8aPavlin Radoslavov L2CAP_FCR_ACK_TIMEOUT_MS, 130978bcff79e1b1f0efce436b33bdd6da88745bfc8aPavlin Radoslavov l2c_fcrb_ack_timer_timeout, p_ccb, 131078bcff79e1b1f0efce436b33bdd6da88745bfc8aPavlin Radoslavov btu_general_alarm_queue); 13115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 13125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 13131a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov else if ((fixed_queue_is_empty(p_ccb->xmit_hold_q) || 13141a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov l2c_fcr_is_flow_controlled(p_ccb)) 13151a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov && fixed_queue_is_empty(p_ccb->fcrb.srej_rcv_hold_q)) 13165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 13175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (p_fcrb->local_busy) 13185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project l2c_fcr_send_S_frame (p_ccb, L2CAP_FCR_SUP_RNR, 0); 13195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project else 13205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project l2c_fcr_send_S_frame (p_ccb, L2CAP_FCR_SUP_RR, 0); 13215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 13225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 13235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 13245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 13255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 13265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 1327ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1328ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function process_stream_frame 1329ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1330ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description This function processes frames in streaming mode 1331ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1332ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns - 1333ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1334ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 13355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic void process_stream_frame (tL2C_CCB *p_ccb, BT_HDR *p_buf) 13365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{ 1337ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton assert(p_ccb != NULL); 1338ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton assert(p_buf != NULL); 1339ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton 1340d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen uint16_t ctrl_word; 1341d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen uint16_t fcs; 1342d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen uint8_t *p; 1343d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen uint8_t tx_seq; 13445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 13455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Verify FCS if using */ 13465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (p_ccb->bypass_fcs != L2CAP_BYPASS_FCS) 13475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 1348d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen p = ((uint8_t *)(p_buf+1)) + p_buf->offset + p_buf->len - L2CAP_FCS_LEN; 13495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 13505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Extract and drop the FCS from the packet */ 13515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project STREAM_TO_UINT16 (fcs, p); 13525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_buf->len -= L2CAP_FCS_LEN; 13535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 13545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (l2c_fcr_rx_get_fcs(p_buf) != fcs) 13555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 1356a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati L2CAP_TRACE_WARNING ("Rx L2CAP PDU: CID: 0x%04x BAD FCS", p_ccb->local_cid); 1357cceb430489a70add1b996d54289867c17f4ac0fdPavlin Radoslavov osi_free(p_buf); 13585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project return; 13595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 13605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 13615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 13625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Get the control word */ 1363d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen p = ((uint8_t *)(p_buf+1)) + p_buf->offset; 13645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 13655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project STREAM_TO_UINT16 (ctrl_word, p); 13665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 13675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_buf->len -= L2CAP_FCR_OVERHEAD; 13685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_buf->offset += L2CAP_FCR_OVERHEAD; 13695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 13705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Make sure it is an I-frame */ 13715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (ctrl_word & L2CAP_FCR_S_FRAME_BIT) 13725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 1373a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati L2CAP_TRACE_WARNING ("Rx L2CAP PDU: CID: 0x%04x BAD S-frame in streaming mode ctrl_word: 0x%04x", p_ccb->local_cid, ctrl_word); 1374cceb430489a70add1b996d54289867c17f4ac0fdPavlin Radoslavov osi_free(p_buf); 13755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project return; 13765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 13775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1378a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati L2CAP_TRACE_EVENT ("L2CAP eRTM Rx I-frame: cid: 0x%04x Len: %u SAR: %-12s TxSeq: %u ReqSeq: %u F: %u", 13795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->local_cid, p_buf->len, 13805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project SAR_types[(ctrl_word & L2CAP_FCR_SAR_BITS) >> L2CAP_FCR_SAR_BITS_SHIFT], 13815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project (ctrl_word & L2CAP_FCR_TX_SEQ_BITS) >> L2CAP_FCR_TX_SEQ_BITS_SHIFT, 13825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project (ctrl_word & L2CAP_FCR_REQ_SEQ_BITS) >> L2CAP_FCR_REQ_SEQ_BITS_SHIFT, 13835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project (ctrl_word & L2CAP_FCR_F_BIT) >> L2CAP_FCR_F_BIT_SHIFT); 13845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 13855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Extract the sequence number */ 13865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project tx_seq = (ctrl_word & L2CAP_FCR_TX_SEQ_BITS) >> L2CAP_FCR_TX_SEQ_BITS_SHIFT; 13875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 13885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Check if tx-sequence is the expected one */ 13895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (tx_seq != p_ccb->fcrb.next_seq_expected) 13905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 1391a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati L2CAP_TRACE_WARNING ("Rx L2CAP PDU: CID: 0x%04x Lost frames Exp: %u Got: %u p_rx_sdu: 0x%08x", 13925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->local_cid, p_ccb->fcrb.next_seq_expected, tx_seq, p_ccb->fcrb.p_rx_sdu); 13935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 13945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Lost one or more packets, so flush the SAR queue */ 1395cceb430489a70add1b996d54289867c17f4ac0fdPavlin Radoslavov osi_free_and_reset((void **)&p_ccb->fcrb.p_rx_sdu); 13965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 13975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 13985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->fcrb.next_seq_expected = (tx_seq + 1) & L2CAP_FCR_SEQ_MODULO; 13995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 14005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (!do_sar_reassembly (p_ccb, p_buf, ctrl_word)) 14015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 14025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Some sort of SAR error, so flush the SAR queue */ 1403cceb430489a70add1b996d54289867c17f4ac0fdPavlin Radoslavov osi_free_and_reset((void **)&p_ccb->fcrb.p_rx_sdu); 14045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 14055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 14065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 14075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 14085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 1409ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1410ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function do_sar_reassembly 1411ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1412ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Process SAR bits and re-assemble frame 1413ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1414ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns true if all OK, else false 1415ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1416ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 1417d19e0785e662e640191a075eda07acce61c2aedaMarie Janssenstatic bool do_sar_reassembly (tL2C_CCB *p_ccb, BT_HDR *p_buf, uint16_t ctrl_word) 14185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{ 1419ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton assert(p_ccb != NULL); 1420ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton assert(p_buf != NULL); 1421ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton 14225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project tL2C_FCRB *p_fcrb = &p_ccb->fcrb; 1423d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen uint16_t sar_type = ctrl_word & L2CAP_FCR_SEG_BITS; 1424d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen bool packet_ok = true; 1425d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen uint8_t *p; 14265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 14275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Check if the SAR state is correct */ 14285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if ((sar_type == L2CAP_FCR_UNSEG_SDU) || (sar_type == L2CAP_FCR_START_SDU)) 14295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 14305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (p_fcrb->p_rx_sdu != NULL) 14315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 1432a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati L2CAP_TRACE_WARNING ("SAR - got unexpected unsegmented or start SDU Expected len: %u Got so far: %u", 14335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_fcrb->rx_sdu_len, p_fcrb->p_rx_sdu->len); 14345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1435d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen packet_ok = false; 14365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 14375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Check the length of the packet */ 14385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if ( (sar_type == L2CAP_FCR_START_SDU) && (p_buf->len < L2CAP_SDU_LEN_OVERHEAD) ) 14395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 1440a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati L2CAP_TRACE_WARNING ("SAR start packet too short: %u", p_buf->len); 1441d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen packet_ok = false; 14425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 14435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 14445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project else 14455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 14465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (p_fcrb->p_rx_sdu == NULL) 14475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 1448a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati L2CAP_TRACE_WARNING ("SAR - got unexpected cont or end SDU"); 1449d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen packet_ok = false; 14505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 14515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 14525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 14535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if ( (packet_ok) && (sar_type != L2CAP_FCR_UNSEG_SDU) ) 14545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 1455d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen p = ((uint8_t *)(p_buf + 1)) + p_buf->offset; 14565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 14575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* For start SDU packet, extract the SDU length */ 14585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (sar_type == L2CAP_FCR_START_SDU) 14595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 14605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Get the SDU length */ 14615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project STREAM_TO_UINT16 (p_fcrb->rx_sdu_len, p); 14625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_buf->offset += 2; 14635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_buf->len -= 2; 14645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 14655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (p_fcrb->rx_sdu_len > p_ccb->max_rx_mtu) 14665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 1467a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati L2CAP_TRACE_WARNING ("SAR - SDU len: %u larger than MTU: %u", p_fcrb->rx_sdu_len, p_fcrb->rx_sdu_len); 1468d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen packet_ok = false; 1469717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov } else { 1470717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov p_fcrb->p_rx_sdu = (BT_HDR *)osi_malloc(L2CAP_MAX_BUF_SIZE); 14712e3d006b96eafb0651fe7f78d28250faf89405dePavlin Radoslavov p_fcrb->p_rx_sdu->offset = OBX_BUF_MIN_OFFSET; 1472717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov p_fcrb->p_rx_sdu->len = 0; 14735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 14745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 14755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 14765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (packet_ok) 14775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 14785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if ((p_fcrb->p_rx_sdu->len + p_buf->len) > p_fcrb->rx_sdu_len) 14795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 1480a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati L2CAP_TRACE_ERROR ("SAR - SDU len exceeded Type: %u Lengths: %u %u %u", 14815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project sar_type, p_fcrb->p_rx_sdu->len, p_buf->len, p_fcrb->rx_sdu_len); 1482d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen packet_ok = false; 14835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 14845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project else if ( (sar_type == L2CAP_FCR_END_SDU) && ((p_fcrb->p_rx_sdu->len + p_buf->len) != p_fcrb->rx_sdu_len) ) 14855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 1486a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati L2CAP_TRACE_WARNING ("SAR - SDU end rcvd but SDU incomplete: %u %u %u", 14875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_fcrb->p_rx_sdu->len, p_buf->len, p_fcrb->rx_sdu_len); 1488d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen packet_ok = false; 14895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 14905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project else 14915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 1492d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen memcpy (((uint8_t *) (p_fcrb->p_rx_sdu + 1)) + p_fcrb->p_rx_sdu->offset + p_fcrb->p_rx_sdu->len, p, p_buf->len); 14935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 14945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_fcrb->p_rx_sdu->len += p_buf->len; 14955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1496cceb430489a70add1b996d54289867c17f4ac0fdPavlin Radoslavov osi_free(p_buf); 14975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_buf = NULL; 14985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 14995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (sar_type == L2CAP_FCR_END_SDU) 15005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 15015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_buf = p_fcrb->p_rx_sdu; 15025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_fcrb->p_rx_sdu = NULL; 15035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 15045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 15055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 15065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 15075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1508d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen if (packet_ok == false) 15095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 1510cceb430489a70add1b996d54289867c17f4ac0fdPavlin Radoslavov osi_free(p_buf); 15115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 15125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project else if (p_buf != NULL) 15135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 15145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_NUM_FIXED_CHNLS > 0) 1515ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta if (p_ccb->local_cid < L2CAP_BASE_APPL_CID && 1516ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta (p_ccb->local_cid >= L2CAP_FIRST_FIXED_CHNL && p_ccb->local_cid <= L2CAP_LAST_FIXED_CHNL)) 1517ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta { 1518ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta if (l2cb.fixed_reg[p_ccb->local_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedData_Cb) 15198372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz (*l2cb.fixed_reg[p_ccb->local_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedData_Cb) 15208372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz (p_ccb->local_cid, p_ccb->p_lcb->remote_bd_addr, p_buf); 1521ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta } 15225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project else 15235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif 15245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project l2c_csm_execute (p_ccb, L2CEVT_L2CAP_DATA, p_buf); 15255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 15265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 15275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project return (packet_ok); 15285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 15295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 15305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 15315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 1532ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1533ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function retransmit_i_frames 1534ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1535ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description This function retransmits i-frames awaiting acks. 1536ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1537ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns bool - true if retransmitted 1538ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1539ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 1540d19e0785e662e640191a075eda07acce61c2aedaMarie Janssenstatic bool retransmit_i_frames (tL2C_CCB *p_ccb, uint8_t tx_seq) 15415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{ 1542ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton assert(p_ccb != NULL); 1543ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton 15441a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov BT_HDR *p_buf = NULL; 1545d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen uint8_t *p; 1546d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen uint8_t buf_seq; 1547d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen uint16_t ctrl_word; 15485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 15491a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov if ( (!fixed_queue_is_empty(p_ccb->fcrb.waiting_for_ack_q)) 15505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project && (p_ccb->peer_cfg.fcr.max_transmit != 0) 15515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project && (p_ccb->fcrb.num_tries >= p_ccb->peer_cfg.fcr.max_transmit) ) 15525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 1553a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati L2CAP_TRACE_EVENT ("Max Tries Exceeded: (last_acq: %d CID: 0x%04x num_tries: %u (max: %u) ack_q_count: %u", 15545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->fcrb.last_rx_ack, p_ccb->local_cid, p_ccb->fcrb.num_tries, p_ccb->peer_cfg.fcr.max_transmit, 15551a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov fixed_queue_length(p_ccb->fcrb.waiting_for_ack_q)); 15565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 15575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project l2cu_disconnect_chnl (p_ccb); 1558d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen return (false); 15595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 15605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 15615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* tx_seq indicates whether to retransmit a specific sequence or all (if == L2C_FCR_RETX_ALL_PKTS) */ 1562577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov list_t *list_ack = NULL; 1563577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov const list_node_t *node_ack = NULL; 1564577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov if (! fixed_queue_is_empty(p_ccb->fcrb.waiting_for_ack_q)) { 1565577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov list_ack = fixed_queue_get_list(p_ccb->fcrb.waiting_for_ack_q); 1566577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov node_ack = list_begin(list_ack); 1567577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov } 15685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (tx_seq != L2C_FCR_RETX_ALL_PKTS) 15695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 15705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* If sending only one, the sequence number tells us which one. Look for it. 15715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project */ 1572577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov if (list_ack != NULL) { 1573577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov for ( ; node_ack != list_end(list_ack); node_ack = list_next(node_ack)) { 1574577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov p_buf = (BT_HDR *)list_node(node_ack); 1575577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov /* Get the old control word */ 1576d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen p = ((uint8_t *) (p_buf+1)) + p_buf->offset + L2CAP_PKT_OVERHEAD; 15775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1578577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov STREAM_TO_UINT16 (ctrl_word, p); 15795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1580577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov buf_seq = (ctrl_word & L2CAP_FCR_TX_SEQ_BITS) >> L2CAP_FCR_TX_SEQ_BITS_SHIFT; 15815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1582577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov L2CAP_TRACE_DEBUG ("retransmit_i_frames() cur seq: %u looking for: %u", buf_seq, tx_seq); 15835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1584577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov if (tx_seq == buf_seq) 1585577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov break; 1586577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov } 15875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 15885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 15895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (!p_buf) 15905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 15911a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov L2CAP_TRACE_ERROR ("retransmit_i_frames() UNKNOWN seq: %u q_count: %u", 15921a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov tx_seq, 15931a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov fixed_queue_length(p_ccb->fcrb.waiting_for_ack_q)); 1594d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen return (true); 15955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 15965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 15975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project else 15985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 15996c303aeca25783453333172d0b29e5472f1b1c93Chris Manton // Iterate though list and flush the amount requested from 16006c303aeca25783453333172d0b29e5472f1b1c93Chris Manton // the transmit data queue that satisfy the layer and event conditions. 16011a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov for (list_node_t *node_tmp = list_begin(p_ccb->p_lcb->link_xmit_data_q); 16021a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov node_tmp != list_end(p_ccb->p_lcb->link_xmit_data_q);) { 16031a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov BT_HDR *p_tmp = (BT_HDR *)list_node(node_tmp); 16041a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov node_tmp = list_next(node_tmp); 16053805ab67b9c973b2afb7475e1a86e35bc18ffd1dChris Manton 16066c303aeca25783453333172d0b29e5472f1b1c93Chris Manton /* Do not flush other CIDs or partial segments */ 16071a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov if ((p_tmp->layer_specific == 0) && (p_tmp->event == p_ccb->local_cid)) { 16081a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov list_remove(p_ccb->p_lcb->link_xmit_data_q, p_tmp); 1609cceb430489a70add1b996d54289867c17f4ac0fdPavlin Radoslavov osi_free(p_tmp); 16106c303aeca25783453333172d0b29e5472f1b1c93Chris Manton } 16115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 16125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 16135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Also flush our retransmission queue */ 16141a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov while (!fixed_queue_is_empty(p_ccb->fcrb.retrans_q)) 1615cceb430489a70add1b996d54289867c17f4ac0fdPavlin Radoslavov osi_free(fixed_queue_try_dequeue(p_ccb->fcrb.retrans_q)); 16165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1617577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov if (list_ack != NULL) 1618577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov node_ack = list_begin(list_ack); 16195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 16205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1621577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov if (list_ack != NULL) { 1622577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov while (node_ack != list_end(list_ack)) 16235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 1624577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov p_buf = (BT_HDR *)list_node(node_ack); 1625577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov node_ack = list_next(node_ack); 16265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1627577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov BT_HDR *p_buf2 = l2c_fcr_clone_buf(p_buf, p_buf->offset, p_buf->len); 1628577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov if (p_buf2) 1629577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov { 1630577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov p_buf2->layer_specific = p_buf->layer_specific; 1631577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov 1632577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov fixed_queue_enqueue(p_ccb->fcrb.retrans_q, p_buf2); 1633577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov } 16345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1635577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov if ( (tx_seq != L2C_FCR_RETX_ALL_PKTS) || (p_buf2 == NULL) ) 1636577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov break; 1637577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov } 16385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 16395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 16405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, NULL); 16415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 16421a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov if (fixed_queue_length(p_ccb->fcrb.waiting_for_ack_q)) 16435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 16445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->fcrb.num_tries++; 16455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project l2c_fcr_start_timer (p_ccb); 16465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 16475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1648d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen return (true); 16495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 16505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 16515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 16525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 1653ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1654ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2c_fcr_get_next_xmit_sdu_seg 1655ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1656ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Get the next SDU segment to transmit. 1657ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1658ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns pointer to buffer with segment or NULL 1659ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1660ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 1661d19e0785e662e640191a075eda07acce61c2aedaMarie JanssenBT_HDR *l2c_fcr_get_next_xmit_sdu_seg (tL2C_CCB *p_ccb, uint16_t max_packet_length) 16625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{ 1663ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton assert(p_ccb != NULL); 1664ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton 1665d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen bool first_seg = false, /* The segment is the first part of data */ 1666d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen mid_seg = false, /* The segment is the middle part of data */ 1667d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen last_seg = false; /* The segment is the last part of data */ 1668d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen uint16_t sdu_len = 0; 16695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project BT_HDR *p_buf, *p_xmit; 1670d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen uint8_t *p; 1671d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen uint16_t max_pdu = p_ccb->tx_mps /* Needed? - L2CAP_MAX_HEADER_FCS*/; 16725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 16735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* If there is anything in the retransmit queue, that goes first 16745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project */ 16751a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov p_buf = (BT_HDR *)fixed_queue_try_dequeue(p_ccb->fcrb.retrans_q); 16761a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov if (p_buf != NULL) 16775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 16785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Update Rx Seq and FCS if we acked some packets while this one was queued */ 1679d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen prepare_I_frame (p_ccb, p_buf, true); 16805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 16815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_buf->event = p_ccb->local_cid; 16825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 16835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ERTM_STATS == TRUE) 16845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->fcrb.pkts_retransmitted++; 16855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->fcrb.ertm_pkt_counts[0]++; 16865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->fcrb.ertm_byte_counts[0] += (p_buf->len - 8); 16875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif 16885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project return (p_buf); 16895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 16905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 16915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* For BD/EDR controller, max_packet_length is set to 0 */ 16925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* For AMP controller, max_packet_length is set by available blocks */ 16935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if ( (max_packet_length > L2CAP_MAX_HEADER_FCS) 16945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project && (max_pdu + L2CAP_MAX_HEADER_FCS > max_packet_length) ) 16955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 16965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project max_pdu = max_packet_length - L2CAP_MAX_HEADER_FCS; 16975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 16985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 16991a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov p_buf = (BT_HDR *)fixed_queue_try_peek_first(p_ccb->xmit_hold_q); 17005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 17015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* If there is more data than the MPS, it requires segmentation */ 17025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (p_buf->len > max_pdu) 17035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 17045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* We are using the "event" field to tell is if we already started segmentation */ 17055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (p_buf->event == 0) 17065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 1707d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen first_seg = true; 17085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project sdu_len = p_buf->len; 17095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 17105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project else 1711d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen mid_seg = true; 17125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 17135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Get a new buffer and copy the data that can be sent in a PDU */ 17142e3d006b96eafb0651fe7f78d28250faf89405dePavlin Radoslavov p_xmit = l2c_fcr_clone_buf(p_buf, L2CAP_MIN_OFFSET + L2CAP_SDU_LEN_OFFSET, 17152e3d006b96eafb0651fe7f78d28250faf89405dePavlin Radoslavov max_pdu); 17165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 17175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (p_xmit != NULL) 17185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 17195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_buf->event = p_ccb->local_cid; 17205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_xmit->event = p_ccb->local_cid; 17215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 17225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_buf->len -= max_pdu; 17235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_buf->offset += max_pdu; 17245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 17255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* copy PBF setting */ 17265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_xmit->layer_specific = p_buf->layer_specific; 17275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 17285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project else /* Should never happen if the application has configured buffers correctly */ 17295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 17302e3d006b96eafb0651fe7f78d28250faf89405dePavlin Radoslavov L2CAP_TRACE_ERROR ("L2CAP - cannot get buffer for segmentation, max_pdu: %u", max_pdu); 17315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project return (NULL); 17325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 17335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 17345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project else /* Use the original buffer if no segmentation, or the last segment */ 17355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 17361a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov p_xmit = (BT_HDR *)fixed_queue_try_dequeue(p_ccb->xmit_hold_q); 17375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 17385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (p_xmit->event != 0) 1739d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen last_seg = true; 17405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 17415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_xmit->event = p_ccb->local_cid; 17425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 17435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 17445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Step back to add the L2CAP headers */ 17455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_xmit->offset -= (L2CAP_PKT_OVERHEAD + L2CAP_FCR_OVERHEAD); 17465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_xmit->len += L2CAP_PKT_OVERHEAD + L2CAP_FCR_OVERHEAD; 17475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 17485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (first_seg) 17495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 17505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_xmit->offset -= L2CAP_SDU_LEN_OVERHEAD; 17515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_xmit->len += L2CAP_SDU_LEN_OVERHEAD; 17525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 17535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 17545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Set the pointer to the beginning of the data */ 1755d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen p = (uint8_t *)(p_xmit + 1) + p_xmit->offset; 17565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 17575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Now the L2CAP header */ 17585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 17595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Note: if FCS has to be included then the length is recalculated later */ 17605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project UINT16_TO_STREAM (p, p_xmit->len - L2CAP_PKT_OVERHEAD); 17615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 17625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project UINT16_TO_STREAM (p, p_ccb->remote_cid); 17635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 17645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (first_seg) 17655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 17665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Skip control word and add SDU length */ 17675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p += 2; 17685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project UINT16_TO_STREAM (p, sdu_len); 17695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 17705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* We will store the SAR type in layer-specific */ 17715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* layer_specific is shared with flushable flag(bits 0-1), don't clear it */ 17725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_xmit->layer_specific |= L2CAP_FCR_START_SDU; 17735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1774d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen first_seg = false; 17755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 17765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project else if (mid_seg) 17775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_xmit->layer_specific |= L2CAP_FCR_CONT_SDU; 17785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project else if (last_seg) 17795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_xmit->layer_specific |= L2CAP_FCR_END_SDU; 17805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project else 17815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_xmit->layer_specific |= L2CAP_FCR_UNSEG_SDU; 17825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1783d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen prepare_I_frame (p_ccb, p_xmit, false); 17845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 17855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) 17865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 17872e3d006b96eafb0651fe7f78d28250faf89405dePavlin Radoslavov BT_HDR *p_wack = l2c_fcr_clone_buf(p_xmit, HCI_DATA_PREAMBLE_SIZE, p_xmit->len); 17885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 17895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (!p_wack) 17905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 17912e3d006b96eafb0651fe7f78d28250faf89405dePavlin Radoslavov L2CAP_TRACE_ERROR("L2CAP - no buffer for xmit cloning, CID: 0x%04x Length: %u", 17922e3d006b96eafb0651fe7f78d28250faf89405dePavlin Radoslavov p_ccb->local_cid, p_xmit->len); 17935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 17945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* We will not save the FCS in case we reconfigure and change options */ 17955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (p_ccb->bypass_fcs != L2CAP_BYPASS_FCS) 17965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_xmit->len -= L2CAP_FCS_LEN; 17975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 17985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Pretend we sent it and it got lost */ 17991a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov fixed_queue_enqueue(p_ccb->fcrb.waiting_for_ack_q, p_xmit); 18005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project return (NULL); 18015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 18025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project else 18035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 18045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ERTM_STATS == TRUE) 18055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* set timestamp at the end of tx I-frame to get acking delay */ 1806871e9ba3063530a81ca7ff03e8433c25e1e8c096Pavlin Radoslavov /* 1807871e9ba3063530a81ca7ff03e8433c25e1e8c096Pavlin Radoslavov * NOTE: Here we assume the allocate buffer is large enough 1808871e9ba3063530a81ca7ff03e8433c25e1e8c096Pavlin Radoslavov * to include extra 4 octets at the end. 1809871e9ba3063530a81ca7ff03e8433c25e1e8c096Pavlin Radoslavov */ 1810d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen p = ((uint8_t *) (p_wack+1)) + p_wack->offset + p_wack->len; 1811c196f214c5ae349ec2022f8d3cbaf56910b3b9f8Pavlin Radoslavov UINT32_TO_STREAM (p, time_get_os_boottime_ms()); 18125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif 18135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* We will not save the FCS in case we reconfigure and change options */ 18145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (p_ccb->bypass_fcs != L2CAP_BYPASS_FCS) 18155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_wack->len -= L2CAP_FCS_LEN; 18165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 18175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_wack->layer_specific = p_xmit->layer_specific; 18181a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov fixed_queue_enqueue(p_ccb->fcrb.waiting_for_ack_q, p_wack); 18195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 18205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 18215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ERTM_STATS == TRUE) 18225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->fcrb.ertm_pkt_counts[0]++; 18235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->fcrb.ertm_byte_counts[0] += (p_xmit->len - 8); 18245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif 18255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 18265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 18275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 18285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project return (p_xmit); 18295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 18305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 18316721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar/******************************************************************************* 1832ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1833ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2c_lcc_get_next_xmit_sdu_seg 1834ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 18359ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Description Get the next SDU segment to transmit for LE connection 18369ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * oriented channel 1837ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1838ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns pointer to buffer with segment or NULL 1839ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1840ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 1841d19e0785e662e640191a075eda07acce61c2aedaMarie JanssenBT_HDR *l2c_lcc_get_next_xmit_sdu_seg (tL2C_CCB *p_ccb, uint16_t max_packet_length) 18426721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar{ 1843d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen bool first_seg = false; /* The segment is the first part of data */ 1844d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen bool last_seg = false; /* The segment is the last part of data */ 1845d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen uint16_t no_of_bytes_to_send = 0; 1846d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen uint16_t sdu_len = 0; 18476721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar BT_HDR *p_buf, *p_xmit; 1848d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen uint8_t *p; 1849d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen uint16_t max_pdu = p_ccb->peer_conn_cfg.mps; 18506721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 18516721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar p_buf = (BT_HDR *)fixed_queue_try_peek_first(p_ccb->xmit_hold_q); 18526721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 18536721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar /* We are using the "event" field to tell is if we already started segmentation */ 18546721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar if (p_buf->event == 0) 18556721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar { 1856d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen first_seg = true; 18576721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar sdu_len = p_buf->len; 18586721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar if (p_buf->len <= (max_pdu - L2CAP_LCC_SDU_LENGTH)) 18596721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar { 1860d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen last_seg = true; 18616721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar no_of_bytes_to_send = p_buf->len; 18626721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar } 18636721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar else 18646721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar no_of_bytes_to_send = max_pdu - L2CAP_LCC_SDU_LENGTH; 18656721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar } 18666721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar else if (p_buf->len <= max_pdu) 18676721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar { 1868d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen last_seg = true; 18696721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar no_of_bytes_to_send = p_buf->len; 18706721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar } 18716721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar else 18726721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar { 18736721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar /* Middle Packet */ 18746721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar no_of_bytes_to_send = max_pdu; 18756721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar } 18766721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 18776721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar /* Get a new buffer and copy the data that can be sent in a PDU */ 1878d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen if (first_seg == true) 18796721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar p_xmit = l2c_fcr_clone_buf (p_buf, L2CAP_LCC_OFFSET, 18806721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar no_of_bytes_to_send); 18816721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar else 18826721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar p_xmit = l2c_fcr_clone_buf (p_buf, L2CAP_MIN_OFFSET, 18836721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar no_of_bytes_to_send); 18846721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 18856721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar if (p_xmit != NULL) 18866721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar { 18876721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar p_buf->event = p_ccb->local_cid; 18886721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar p_xmit->event = p_ccb->local_cid; 18896721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 1890d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen if (first_seg == true) 18916721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar { 18926721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar p_xmit->offset -= L2CAP_LCC_SDU_LENGTH; /* for writing the SDU length. */ 1893d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen p = (uint8_t *)(p_xmit + 1) + p_xmit->offset; 18946721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar UINT16_TO_STREAM(p, sdu_len); 18956721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar p_xmit->len += L2CAP_LCC_SDU_LENGTH; 18966721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar } 18976721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 18986721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar p_buf->len -= no_of_bytes_to_send; 18996721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar p_buf->offset += no_of_bytes_to_send; 19006721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 19016721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar /* copy PBF setting */ 19026721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar p_xmit->layer_specific = p_buf->layer_specific; 19036721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 19046721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar } 19056721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar else /* Should never happen if the application has configured buffers correctly */ 19066721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar { 19076721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar L2CAP_TRACE_ERROR ("L2CAP - cannot get buffer, for segmentation"); 19086721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar return (NULL); 19096721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar } 19106721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 1911d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen if (last_seg == true) 19126721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar { 19136721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar p_buf = (BT_HDR *)fixed_queue_try_dequeue(p_ccb->xmit_hold_q); 19146721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar osi_free(p_buf); 19156721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar } 19166721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 19176721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar /* Step back to add the L2CAP headers */ 19186721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar p_xmit->offset -= L2CAP_PKT_OVERHEAD; 19196721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar p_xmit->len += L2CAP_PKT_OVERHEAD ; 19206721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 19216721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar /* Set the pointer to the beginning of the data */ 1922d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen p = (uint8_t *)(p_xmit + 1) + p_xmit->offset; 19236721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 19246721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar /* Note: if FCS has to be included then the length is recalculated later */ 19256721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar UINT16_TO_STREAM (p, p_xmit->len - L2CAP_PKT_OVERHEAD); 19266721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar UINT16_TO_STREAM (p, p_ccb->remote_cid); 19276721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar return (p_xmit); 19286721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar 19296721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar} 19305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 19315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 1932ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Configuration negotiation functions 1933ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1934ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * The following functions are used in negotiating channel modes during 1935ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * configuration 1936ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 19375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 19385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 1939ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1940ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2c_fcr_chk_chan_modes 1941ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1942ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Validates and adjusts if necessary, the FCR options 1943ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * based on remote EXT features. 1944ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1945ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Note: This assumes peer EXT Features have been received. 1946ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Basic mode is used if FCR Options have not been received 1947ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 19489ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Returns uint8_t - nonzero if can continue, '0' if no compatible 19499ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * channels 1950ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1951ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 1952d19e0785e662e640191a075eda07acce61c2aedaMarie Janssenuint8_t l2c_fcr_chk_chan_modes (tL2C_CCB *p_ccb) 19535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{ 1954ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton assert(p_ccb != NULL); 1955ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton 19565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Remove nonbasic options that the peer does not support */ 19575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (!(p_ccb->p_lcb->peer_ext_fea & L2CAP_EXTFEA_ENH_RETRANS)) 19585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->ertm_info.allowed_modes &= ~L2CAP_FCR_CHAN_OPT_ERTM; 19595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 19605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (!(p_ccb->p_lcb->peer_ext_fea & L2CAP_EXTFEA_STREAM_MODE)) 19615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->ertm_info.allowed_modes &= ~L2CAP_FCR_CHAN_OPT_STREAM; 19625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 19635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* At least one type needs to be set (Basic, ERTM, STM) to continue */ 19645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (!p_ccb->ertm_info.allowed_modes) 19655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 1966a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati L2CAP_TRACE_WARNING ("L2CAP - Peer does not support our desired channel types"); 19675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 19685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 19695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project return (p_ccb->ertm_info.allowed_modes); 19705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 19715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 19725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 1973ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1974ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2c_fcr_adj_our_req_options 1975ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1976ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Validates and sets up the FCR options passed in from 1977ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * L2CA_ConfigReq based on remote device's features. 1978ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1979ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns true if no errors, Otherwise false 1980ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1981ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 1982d19e0785e662e640191a075eda07acce61c2aedaMarie Janssenbool l2c_fcr_adj_our_req_options (tL2C_CCB *p_ccb, tL2CAP_CFG_INFO *p_cfg) 19835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{ 1984ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton assert(p_ccb != NULL); 1985ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton assert(p_cfg != NULL); 1986ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton 19875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project tL2CAP_FCR_OPTS *p_fcr = &p_cfg->fcr; 19885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 19895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (p_fcr->mode != p_ccb->ertm_info.preferred_mode) 19905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 1991a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati L2CAP_TRACE_WARNING ("l2c_fcr_adj_our_req_options - preferred_mode (%d), does not match mode (%d)", 19925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->ertm_info.preferred_mode, p_fcr->mode); 19935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 19945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* The preferred mode is passed in through tL2CAP_ERTM_INFO, so override this one */ 19955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_fcr->mode = p_ccb->ertm_info.preferred_mode; 19965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 19975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 19985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* If upper layer did not request eRTM mode, BASIC must be used */ 19995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (p_ccb->ertm_info.allowed_modes == L2CAP_FCR_CHAN_OPT_BASIC) 20005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 20015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (p_cfg->fcr_present && p_fcr->mode != L2CAP_FCR_BASIC_MODE) 20025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 2003a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati L2CAP_TRACE_WARNING ("l2c_fcr_adj_our_req_options (mode %d): ERROR: No FCR options set using BASIC mode", p_fcr->mode); 20045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 20055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_fcr->mode = L2CAP_FCR_BASIC_MODE; 20065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 20075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 20085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Process the FCR options if initial channel bring-up (not a reconfig request) 20095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ** Determine initial channel mode to try based on our options and remote's features 20105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project */ 20115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (p_cfg->fcr_present && !(p_ccb->config_done & RECONFIG_FLAG)) 20125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 20135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* We need to have at least one mode type common with the peer */ 20145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (!l2c_fcr_chk_chan_modes(p_ccb)) 20155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 20165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Two channels have incompatible supported types */ 20175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project l2cu_disconnect_chnl (p_ccb); 2018d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen return (false); 20195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 20205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 20215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Basic is the only common channel mode between the two devices */ 20225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project else if (p_ccb->ertm_info.allowed_modes == L2CAP_FCR_CHAN_OPT_BASIC) 20235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 20245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* We only want to try Basic, so bypass sending the FCR options entirely */ 2025d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen p_cfg->fcr_present = false; 2026d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen p_cfg->fcs_present = false; /* Illegal to use FCS option in basic mode */ 2027d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen p_cfg->ext_flow_spec_present = false; /* Illegal to use extended flow spec in basic mode */ 20285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 20295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 20305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* We have at least one non-basic mode available 20315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * Override mode from available mode options based on preference, if needed 20325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project */ 20335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project else 20345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 20355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* If peer does not support STREAMING, try ERTM */ 20365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (p_fcr->mode == L2CAP_FCR_STREAM_MODE && !(p_ccb->ertm_info.allowed_modes & L2CAP_FCR_CHAN_OPT_STREAM)) 20375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 2038a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati L2CAP_TRACE_DEBUG ("L2C CFG: mode is STREAM, but peer does not support; Try ERTM"); 20395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_fcr->mode = L2CAP_FCR_ERTM_MODE; 20405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 20415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 20425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* If peer does not support ERTM, try BASIC (will support this if made it here in the code) */ 20435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (p_fcr->mode == L2CAP_FCR_ERTM_MODE && !(p_ccb->ertm_info.allowed_modes & L2CAP_FCR_CHAN_OPT_ERTM)) 20445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 2045a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati L2CAP_TRACE_DEBUG ("L2C CFG: mode is ERTM, but peer does not support; Try BASIC"); 20465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_fcr->mode = L2CAP_FCR_BASIC_MODE; 20475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 20485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 20495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 20505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (p_fcr->mode != L2CAP_FCR_BASIC_MODE) 20515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 20525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* MTU must be smaller than buffer size */ 20535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if ( (p_cfg->mtu_present) && (p_cfg->mtu > p_ccb->max_rx_mtu) ) 20545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 2055a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati L2CAP_TRACE_WARNING ("L2CAP - MTU: %u larger than buf size: %u", p_cfg->mtu, p_ccb->max_rx_mtu); 2056d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen return (false); 20575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 20585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 20595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* application want to use the default MPS */ 20605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (p_fcr->mps == L2CAP_DEFAULT_ERM_MPS) 20615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 20625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_fcr->mps = L2CAP_MPS_OVER_BR_EDR; 20635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 20645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* MPS must be less than MTU */ 20655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project else if (p_fcr->mps > p_ccb->max_rx_mtu) 20665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 2067a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati L2CAP_TRACE_WARNING ("L2CAP - MPS %u invalid MTU: %u", p_fcr->mps, p_ccb->max_rx_mtu); 2068d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen return (false); 20695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 20705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 20715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* We always initially read into the HCI buffer pool, so make sure it fits */ 20725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (p_fcr->mps > (L2CAP_MTU_SIZE - L2CAP_MAX_HEADER_FCS)) 20735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_fcr->mps = L2CAP_MTU_SIZE - L2CAP_MAX_HEADER_FCS; 20745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 20755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project else 20765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 2077d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen p_cfg->fcs_present = false; /* Illegal to use FCS option in basic mode */ 2078d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen p_cfg->ext_flow_spec_present = false; /* Illegal to use extended flow spec in basic mode */ 20795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 20805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 20815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->our_cfg.fcr = *p_fcr; 20825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 20835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project else /* Not sure how to send a reconfiguration(??) should fcr be included? */ 20845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 2085d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen p_ccb->our_cfg.fcr_present = false; 20865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 20875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2088d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen return (true); 20895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 20905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 20915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 20925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 2093ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2094ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2c_fcr_adj_monitor_retran_timeout 2095ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2096ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Overrides monitor/retrans timer value based on controller 2097ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2098ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns None 2099ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2100ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 21015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectvoid l2c_fcr_adj_monitor_retran_timeout (tL2C_CCB *p_ccb) 21025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{ 2103ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton assert(p_ccb != NULL); 2104ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton 21055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* adjust our monitor/retran timeout */ 21065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (p_ccb->out_cfg_fcr_present) 21075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 21085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* 21095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ** if we requestd ERTM or accepted ERTM 21105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ** We may accept ERTM even if we didn't request ERTM, in case of requesting STREAM 21115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project */ 21125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if ((p_ccb->our_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) 21135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ||(p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE)) 21145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 21155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* upper layer setting is ignored */ 21165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->our_cfg.fcr.mon_tout = L2CAP_MIN_MONITOR_TOUT; 21175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->our_cfg.fcr.rtrans_tout = L2CAP_MIN_RETRANS_TOUT; 21185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 21195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project else 21205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 21215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->our_cfg.fcr.mon_tout = 0; 21225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->our_cfg.fcr.rtrans_tout = 0; 21235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 21245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2125a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati L2CAP_TRACE_DEBUG ("l2c_fcr_adj_monitor_retran_timeout: mon_tout:%d, rtrans_tout:%d", 21265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->our_cfg.fcr.mon_tout, p_ccb->our_cfg.fcr.rtrans_tout); 21275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 21285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 21295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 2130ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2131ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2c_fcr_adj_our_rsp_options 2132ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2133ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Overrides any neccesary FCR options passed in from 2134ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * L2CA_ConfigRsp based on our FCR options. 2135ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Only makes adjustments if channel is in ERTM mode. 2136ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2137ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns None 2138ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2139ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 21405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectvoid l2c_fcr_adj_our_rsp_options (tL2C_CCB *p_ccb, tL2CAP_CFG_INFO *p_cfg) 21415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{ 2142ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton assert(p_ccb != NULL); 2143ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton assert(p_cfg != NULL); 2144ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton 21455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* adjust our monitor/retran timeout */ 21465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project l2c_fcr_adj_monitor_retran_timeout(p_ccb); 21475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 21485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_cfg->fcr_present = p_ccb->out_cfg_fcr_present; 21495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 21505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (p_cfg->fcr_present) 21515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 21525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Temporary - until a better algorithm is implemented */ 21535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* If peer's tx_wnd_sz requires too many buffers for us to support, then adjust it. For now, respond with our own tx_wnd_sz. */ 21545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Note: peer is not guaranteed to obey our adjustment */ 21555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (p_ccb->peer_cfg.fcr.tx_win_sz > p_ccb->our_cfg.fcr.tx_win_sz) 21565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 2157d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen L2CAP_TRACE_DEBUG ("%s: adjusting requested tx_win_sz from %i to %i", __func__, p_ccb->peer_cfg.fcr.tx_win_sz, p_ccb->our_cfg.fcr.tx_win_sz); 21585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->peer_cfg.fcr.tx_win_sz = p_ccb->our_cfg.fcr.tx_win_sz; 21595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 21605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 21615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_cfg->fcr.mode = p_ccb->peer_cfg.fcr.mode; 21625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_cfg->fcr.tx_win_sz = p_ccb->peer_cfg.fcr.tx_win_sz; 21635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_cfg->fcr.max_transmit = p_ccb->peer_cfg.fcr.max_transmit; 21645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_cfg->fcr.mps = p_ccb->peer_cfg.fcr.mps; 21655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_cfg->fcr.rtrans_tout = p_ccb->our_cfg.fcr.rtrans_tout; 21665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_cfg->fcr.mon_tout = p_ccb->our_cfg.fcr.mon_tout; 21675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 21685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 21695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 21705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 2171ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2172ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2c_fcr_renegotiate_chan 2173ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2174ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Called upon unsuccessful peer response to config request. 2175ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * If the error is because of the channel mode, it will try 2176ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * to resend using another supported optional channel. 2177ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2178ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns true if resent configuration, False if channel matches or 2179ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * cannot match. 2180ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2181ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 2182d19e0785e662e640191a075eda07acce61c2aedaMarie Janssenbool l2c_fcr_renegotiate_chan(tL2C_CCB *p_ccb, tL2CAP_CFG_INFO *p_cfg) 21835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{ 2184ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton assert(p_ccb != NULL); 2185ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton assert(p_cfg != NULL); 2186ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton 2187d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen uint8_t peer_mode = p_ccb->our_cfg.fcr.mode; 2188d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen bool can_renegotiate; 21895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 21905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Skip if this is a reconfiguration from OPEN STATE or if FCR is not returned */ 21915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (!p_cfg->fcr_present || (p_ccb->config_done & RECONFIG_FLAG)) 2192d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen return (false); 21935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 21945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Only retry if there are more channel options to try */ 21955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (p_cfg->result == L2CAP_CFG_UNACCEPTABLE_PARAMS) 21965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 21975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project peer_mode = (p_cfg->fcr_present) ? p_cfg->fcr.mode : L2CAP_FCR_BASIC_MODE; 21985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 21995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (p_ccb->our_cfg.fcr.mode != peer_mode) 22005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 22015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 22025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if ((--p_ccb->fcr_cfg_tries) == 0) 22035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 22045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_cfg->result = L2CAP_CFG_FAILED_NO_REASON; 2205a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati L2CAP_TRACE_WARNING ("l2c_fcr_renegotiate_chan (Max retries exceeded)"); 22065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 22075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2208d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen can_renegotiate = false; 22095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 22105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Try another supported mode if available based on our last attempted channel */ 22115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project switch (p_ccb->our_cfg.fcr.mode) 22125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 22135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Our Streaming mode request was unnacceptable; try ERTM or Basic */ 22145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project case L2CAP_FCR_STREAM_MODE: 22155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Peer wants ERTM and we support it */ 22165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if ( (peer_mode == L2CAP_FCR_ERTM_MODE) && (p_ccb->ertm_info.allowed_modes & L2CAP_FCR_CHAN_OPT_ERTM) ) 22175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 2218a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati L2CAP_TRACE_DEBUG ("l2c_fcr_renegotiate_chan(Trying ERTM)"); 22195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->our_cfg.fcr.mode = L2CAP_FCR_ERTM_MODE; 2220d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen can_renegotiate = true; 22215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 22225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project else /* Falls through */ 22235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 22245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project case L2CAP_FCR_ERTM_MODE: 22255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 22265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* We can try basic for any other peer mode if we support it */ 22275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (p_ccb->ertm_info.allowed_modes & L2CAP_FCR_CHAN_OPT_BASIC) 22285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 2229a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati L2CAP_TRACE_DEBUG ("l2c_fcr_renegotiate_chan(Trying Basic)"); 2230d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen can_renegotiate = true; 22315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->our_cfg.fcr.mode = L2CAP_FCR_BASIC_MODE; 22325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 22335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 22345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project break; 22355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 22365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project default: 22375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* All other scenarios cannot be renegotiated */ 22385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project break; 22395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 22405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 22415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (can_renegotiate) 22425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 2243d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen p_ccb->our_cfg.fcr_present = true; 22445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 22455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (p_ccb->our_cfg.fcr.mode == L2CAP_FCR_BASIC_MODE) 22465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 2247d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen p_ccb->our_cfg.fcs_present = false; 2248d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen p_ccb->our_cfg.ext_flow_spec_present = false; 22495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 22505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Basic Mode uses ACL Data Pool, make sure the MTU fits */ 22515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if ( (p_cfg->mtu_present) && (p_cfg->mtu > L2CAP_MTU_SIZE) ) 22525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 2253a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati L2CAP_TRACE_WARNING ("L2CAP - adjust MTU: %u too large", p_cfg->mtu); 22545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_cfg->mtu = L2CAP_MTU_SIZE; 22555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 22565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 22575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 22585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project l2cu_process_our_cfg_req (p_ccb, &p_ccb->our_cfg); 22595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project l2cu_send_peer_config_req (p_ccb, &p_ccb->our_cfg); 226078bcff79e1b1f0efce436b33bdd6da88745bfc8aPavlin Radoslavov alarm_set_on_queue(p_ccb->l2c_ccb_timer, 226178bcff79e1b1f0efce436b33bdd6da88745bfc8aPavlin Radoslavov L2CAP_CHNL_CFG_TIMEOUT_MS, 226278bcff79e1b1f0efce436b33bdd6da88745bfc8aPavlin Radoslavov l2c_ccb_timer_timeout, p_ccb, 226378bcff79e1b1f0efce436b33bdd6da88745bfc8aPavlin Radoslavov btu_general_alarm_queue); 2264d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen return (true); 22655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 22665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 22675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 22685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 22695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Disconnect if the channels do not match */ 22705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (p_ccb->our_cfg.fcr.mode != peer_mode) 22715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 2272a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati L2CAP_TRACE_WARNING ("L2C CFG: Channels incompatible (local %d, peer %d)", 22735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->our_cfg.fcr.mode, peer_mode); 22745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project l2cu_disconnect_chnl (p_ccb); 22755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 22765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2277d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen return (false); 22785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 22795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 22805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 22815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 2282ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2283ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2c_fcr_process_peer_cfg_req 2284ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2285ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description This function is called to process the FCR options passed 2286ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * in the peer's configuration request. 2287ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2288ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns uint8_t - L2CAP_PEER_CFG_OK, L2CAP_PEER_CFG_UNACCEPTABLE, 2289ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * or L2CAP_PEER_CFG_DISCONNECT. 2290ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2291ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 2292d19e0785e662e640191a075eda07acce61c2aedaMarie Janssenuint8_t l2c_fcr_process_peer_cfg_req(tL2C_CCB *p_ccb, tL2CAP_CFG_INFO *p_cfg) 22935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{ 2294ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton assert(p_ccb != NULL); 2295ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton assert(p_cfg != NULL); 2296ca9ec85560ac0b43f2c65f08a7374a14b510e08eChris Manton 2297d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen uint16_t max_retrans_size; 2298d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen uint8_t fcr_ok = L2CAP_PEER_CFG_OK; 22995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2300d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen p_ccb->p_lcb->w4_info_rsp = false; /* Handles T61x SonyEricsson Bug in Info Request */ 23015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2302a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati L2CAP_TRACE_EVENT ("l2c_fcr_process_peer_cfg_req() CFG fcr_present:%d fcr.mode:%d CCB FCR mode:%d preferred: %u allowed:%u", 23035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_cfg->fcr_present, p_cfg->fcr.mode, p_ccb->our_cfg.fcr.mode, p_ccb->ertm_info.preferred_mode, 23045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->ertm_info.allowed_modes); 23055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 23065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* If Peer wants basic, we are done (accept it or disconnect) */ 23075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (p_cfg->fcr.mode == L2CAP_FCR_BASIC_MODE) 23085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 23095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* If we do not allow basic, disconnect */ 23105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if ( !(p_ccb->ertm_info.allowed_modes & L2CAP_FCR_CHAN_OPT_BASIC) ) 23115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project fcr_ok = L2CAP_PEER_CFG_DISCONNECT; 23125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 23135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 23145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Need to negotiate if our modes are not the same */ 23155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project else if (p_cfg->fcr.mode != p_ccb->ertm_info.preferred_mode) 23165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 23175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* If peer wants a mode that we don't support then retry our mode (ex. rtx/flc), OR 23185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ** If we want ERTM and they wanted streaming retry our mode. 23195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ** Note: If we have already determined they support our mode previously 23205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ** from their EXF mask. 23215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project */ 23225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if ( (((1 << p_cfg->fcr.mode) & L2CAP_FCR_CHAN_OPT_ALL_MASK) == 0) 23235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project || (p_ccb->ertm_info.preferred_mode == L2CAP_FCR_ERTM_MODE) ) 23245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 23255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_cfg->fcr.mode = p_ccb->our_cfg.fcr.mode; 23265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_cfg->fcr.tx_win_sz = p_ccb->our_cfg.fcr.tx_win_sz; 23275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_cfg->fcr.max_transmit = p_ccb->our_cfg.fcr.max_transmit; 23285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project fcr_ok = L2CAP_PEER_CFG_UNACCEPTABLE; 23295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 23305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 23315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* If we wanted basic, then try to renegotiate it */ 23325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project else if (p_ccb->ertm_info.preferred_mode == L2CAP_FCR_BASIC_MODE) 23335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 23345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_cfg->fcr.mode = L2CAP_FCR_BASIC_MODE; 23355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_cfg->fcr.max_transmit = p_cfg->fcr.tx_win_sz = 0; 23365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_cfg->fcr.rtrans_tout = p_cfg->fcr.mon_tout = p_cfg->fcr.mps = 0; 23375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->our_cfg.fcr.rtrans_tout = p_ccb->our_cfg.fcr.mon_tout = p_ccb->our_cfg.fcr.mps = 0; 23385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project fcr_ok = L2CAP_PEER_CFG_UNACCEPTABLE; 23395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 23405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 23415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Only other valid case is if they want ERTM and we wanted STM which should be 23425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project accepted if we support it; otherwise the channel should be disconnected */ 23435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project else if ( (p_cfg->fcr.mode != L2CAP_FCR_ERTM_MODE) 23445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project || !(p_ccb->ertm_info.allowed_modes & L2CAP_FCR_CHAN_OPT_ERTM) ) 23455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 23465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project fcr_ok = L2CAP_PEER_CFG_DISCONNECT; 23475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 23485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 23495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 23505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Configuration for FCR channels so make any adjustments and fwd to upper layer */ 23515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (fcr_ok == L2CAP_PEER_CFG_OK) 23525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 23535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* by default don't need to send params in the response */ 2354d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen p_ccb->out_cfg_fcr_present = false; 23555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 23565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Make any needed adjustments for the response to the peer */ 23575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (p_cfg->fcr_present && p_cfg->fcr.mode != L2CAP_FCR_BASIC_MODE) 23585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 23595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Peer desires to bypass FCS check, and streaming or ERTM mode */ 23605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (p_cfg->fcs_present) 23615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 23625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->peer_cfg.fcs = p_cfg->fcs; 23635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->peer_cfg_bits |= L2CAP_CH_CFG_MASK_FCS; 23645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if( p_cfg->fcs == L2CAP_CFG_FCS_BYPASS) 23655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->bypass_fcs |= L2CAP_CFG_FCS_PEER; 23665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 23675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 23681d5b85924df3a114efe6588e857d0de3eb47b1d2Pavlin Radoslavov max_retrans_size = p_ccb->ertm_info.fcr_tx_buf_size - sizeof(BT_HDR) 23695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project - L2CAP_MIN_OFFSET - L2CAP_SDU_LEN_OFFSET - L2CAP_FCS_LEN; 23705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 23715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Ensure the MPS is not bigger than the MTU */ 23725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if ( (p_cfg->fcr.mps == 0) || (p_cfg->fcr.mps > p_ccb->peer_cfg.mtu) ) 23735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 23745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_cfg->fcr.mps = p_ccb->peer_cfg.mtu; 2375d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen p_ccb->out_cfg_fcr_present = true; 23765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 23775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 23785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Ensure the MPS is not bigger than our retransmission buffer */ 23795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (p_cfg->fcr.mps > max_retrans_size) 23805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 2381a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati L2CAP_TRACE_DEBUG("CFG: Overriding MPS to %d (orig %d)", max_retrans_size, p_cfg->fcr.mps); 23825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 23835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_cfg->fcr.mps = max_retrans_size; 2384d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen p_ccb->out_cfg_fcr_present = true; 23855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 23865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 23878fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta if (p_cfg->fcr.mode == L2CAP_FCR_ERTM_MODE || p_cfg->fcr.mode == L2CAP_FCR_STREAM_MODE) 23885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 23895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Always respond with FCR ERTM parameters */ 2390d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen p_ccb->out_cfg_fcr_present = true; 23915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 23925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 23935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 23945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Everything ok, so save the peer's adjusted fcr options */ 23955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->peer_cfg.fcr = p_cfg->fcr; 23965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 23975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (p_cfg->fcr_present) 23985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->peer_cfg_bits |= L2CAP_CH_CFG_MASK_FCR; 23995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 24005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project else if (fcr_ok == L2CAP_PEER_CFG_UNACCEPTABLE) 24015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 24025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* Allow peer only one retry for mode */ 24035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (p_ccb->peer_cfg_already_rejected) 24045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project fcr_ok = L2CAP_PEER_CFG_DISCONNECT; 24055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project else 2406d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen p_ccb->peer_cfg_already_rejected = true; 24075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 24085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 24095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project return (fcr_ok); 24105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 24115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 24125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ERTM_STATS == TRUE) 24135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 2414ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2415ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function l2c_fcr_collect_ack_delay 2416ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2417ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description collect throughput, delay, queue size of waiting ack 2418ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2419ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Parameters 2420ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * tL2C_CCB 2421ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2422ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns void 2423ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 2424ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 2425d19e0785e662e640191a075eda07acce61c2aedaMarie Janssenstatic void l2c_fcr_collect_ack_delay (tL2C_CCB *p_ccb, uint8_t num_bufs_acked) 24265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{ 2427d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen uint32_t index; 24285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project BT_HDR *p_buf; 2429d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen uint8_t *p; 2430d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen uint32_t timestamp, delay; 2431d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen uint8_t xx; 2432d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen uint8_t str[120]; 24335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 24345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project index = p_ccb->fcrb.ack_delay_avg_index; 24355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 24365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* update sum, max and min of waiting for ack queue size */ 24371a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov p_ccb->fcrb.ack_q_count_avg[index] += 24381a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov fixed_queue_length(p_ccb->fcrb.waiting_for_ack_q); 24395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 24401a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov if (fixed_queue_length(p_ccb->fcrb.waiting_for_ack_q) > p_ccb->fcrb.ack_q_count_max[index]) 24411a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov p_ccb->fcrb.ack_q_count_max[index] = fixed_queue_length(p_ccb->fcrb.waiting_for_ack_q); 24425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 24431a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov if (fixed_queue_length(p_ccb->fcrb.waiting_for_ack_q) < p_ccb->fcrb.ack_q_count_min[index]) 24441a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov p_ccb->fcrb.ack_q_count_min[index] = fixed_queue_length(p_ccb->fcrb.waiting_for_ack_q); 24455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 24465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* update sum, max and min of round trip delay of acking */ 2447577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov list_t *list = NULL; 2448577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov if (! fixed_queue_is_empty(p_ccb->fcrb.waiting_for_ack_q)) 2449577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov list = fixed_queue_get_list(p_ccb->fcrb.waiting_for_ack_q); 2450577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov if (list != NULL) { 2451577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov for (const list_node_t *node = list_begin(list), xx = 0; 2452577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov (node != list_end(list)) && (xx < num_bufs_acked); 2453577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov node = list_next(node), xx++) { 2454577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov p_buf = list_node(node); 2455577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov /* adding up length of acked I-frames to get throughput */ 2456577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov p_ccb->fcrb.throughput[index] += p_buf->len - 8; 2457577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov 2458577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov if ( xx == num_bufs_acked - 1 ) 24595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 2460577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov /* get timestamp from tx I-frame that receiver is acking */ 2461d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen p = ((uint8_t *) (p_buf+1)) + p_buf->offset + p_buf->len; 2462577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov if (p_ccb->bypass_fcs != L2CAP_BYPASS_FCS) 2463577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov { 2464577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov p += L2CAP_FCS_LEN; 2465577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov } 24665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2467577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov STREAM_TO_UINT32(timestamp, p); 2468577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov delay = time_get_os_boottime_ms() - timestamp; 24695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2470577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov p_ccb->fcrb.ack_delay_avg[index] += delay; 2471577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov if ( delay > p_ccb->fcrb.ack_delay_max[index] ) 2472577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov p_ccb->fcrb.ack_delay_max[index] = delay; 2473577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov if ( delay < p_ccb->fcrb.ack_delay_min[index] ) 2474577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov p_ccb->fcrb.ack_delay_min[index] = delay; 2475577862e0d87891164a469afcecd1135bf04d1f6ePavlin Radoslavov } 24765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 24775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 24785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 24795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->fcrb.ack_delay_avg_count++; 24805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 24815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* calculate average and initialize next avg, min and max */ 24825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project if (p_ccb->fcrb.ack_delay_avg_count > L2CAP_ERTM_STATS_AVG_NUM_SAMPLES) 24835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project { 24845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->fcrb.ack_delay_avg_count = 0; 24855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 24865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->fcrb.ack_q_count_avg[index] /= L2CAP_ERTM_STATS_AVG_NUM_SAMPLES; 24875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->fcrb.ack_delay_avg[index] /= L2CAP_ERTM_STATS_AVG_NUM_SAMPLES; 24885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 24895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project /* calculate throughput */ 2490c196f214c5ae349ec2022f8d3cbaf56910b3b9f8Pavlin Radoslavov timestamp = time_get_os_boottime_ms(); 2491c196f214c5ae349ec2022f8d3cbaf56910b3b9f8Pavlin Radoslavov if (timestamp - p_ccb->fcrb.throughput_start > 0) 24925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->fcrb.throughput[index] /= (timestamp - p_ccb->fcrb.throughput_start); 24935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 24945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->fcrb.throughput_start = timestamp; 24955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 249680d7f60680f483a71e413f2453ab20013aff5c5cGeorge Burgess IV snprintf(str, sizeof(str), "[%02u] throughput: %5u, ack_delay avg:%3u, min:%3u, max:%3u, ack_q_count avg:%3u, min:%3u, max:%3u", 24975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project index, p_ccb->fcrb.throughput[index], 24985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->fcrb.ack_delay_avg[index], p_ccb->fcrb.ack_delay_min[index], p_ccb->fcrb.ack_delay_max[index], 24995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->fcrb.ack_q_count_avg[index], p_ccb->fcrb.ack_q_count_min[index], p_ccb->fcrb.ack_q_count_max[index] ); 25005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 25010212487880be33e255d49f6e38dbb035d1f77750Sharvil Nanavati BT_TRACE(TRACE_CTRL_GENERAL | TRACE_LAYER_GKI | TRACE_ORG_GKI , TRACE_TYPE_GENERIC, "%s", str); 25025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 25035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project index = (index + 1) % L2CAP_ERTM_STATS_NUM_AVG; 25045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->fcrb.ack_delay_avg_index = index; 25055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 25065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->fcrb.ack_q_count_max[index] = 0; 25075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->fcrb.ack_q_count_min[index] = 0xFFFFFFFF; 25085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->fcrb.ack_q_count_avg[index] = 0; 25095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 25105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 25115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->fcrb.ack_delay_max[index] = 0; 25125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->fcrb.ack_delay_min[index] = 0xFFFFFFFF; 25135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->fcrb.ack_delay_avg[index] = 0; 25145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 25155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project p_ccb->fcrb.throughput[index] = 0; 25165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 25175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 25185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif 2519