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
265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include <stdlib.h>
275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include <string.h>
285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include <stdio.h>
295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "gki.h"
315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "bt_types.h"
325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "hcimsgs.h"
335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "l2cdefs.h"
345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "l2c_int.h"
355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "l2c_api.h"
365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "btu.h"
375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "btm_api.h"
385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "btm_int.h"
395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/* Flag passed to retransmit_i_frames() when all packets should be retransmitted */
425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#define L2C_FCR_RETX_ALL_PKTS   0xFF
435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if BT_TRACE_VERBOSE == TRUE
455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic char *SAR_types[] = { "Unsegmented", "Start", "End", "Continuation" };
465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic char *SUP_types[] = { "RR", "REJ", "RNR", "SREJ" };
475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/* Look-up table for the CRC calculation */
505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic const unsigned short crctab[256] = {
515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241,
525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440,
535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40,
545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841,
555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40,
565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41,
575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641,
585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040,
595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240,
605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441,
615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41,
625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840,
635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41,
645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40,
655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640,
665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041,
675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240,
685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441,
695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41,
705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840,
715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41,
725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40,
735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640,
745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041,
755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241,
765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440,
775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40,
785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841,
795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40,
805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41,
815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641,
825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040,
835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project};
845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**  Static local functions
885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*/
895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic BOOLEAN process_reqseq (tL2C_CCB *p_ccb, UINT16 ctrl_word);
905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic void    process_s_frame (tL2C_CCB *p_ccb, BT_HDR *p_buf, UINT16 ctrl_word);
915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic void    process_i_frame (tL2C_CCB *p_ccb, BT_HDR *p_buf, UINT16 ctrl_word, BOOLEAN delay_ack);
925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic BOOLEAN retransmit_i_frames (tL2C_CCB *p_ccb, UINT8 tx_seq);
935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic void    prepare_I_frame (tL2C_CCB *p_ccb, BT_HDR *p_buf, BOOLEAN is_retransmission);
945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic void    process_stream_frame (tL2C_CCB *p_ccb, BT_HDR *p_buf);
955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic BOOLEAN do_sar_reassembly (tL2C_CCB *p_ccb, BT_HDR *p_buf, UINT16 ctrl_word);
965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if L2CAP_CORRUPT_ERTM_PKTS == TRUE
985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic BOOLEAN l2c_corrupt_the_fcr_packet (tL2C_CCB *p_ccb, BT_HDR *p_buf,
995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                                           BOOLEAN is_rx, UINT16 ctrl_word);
1005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic BOOLEAN l2c_bypass_sframe_packet (tL2C_CCB *p_ccb);
1015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
1025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ERTM_STATS == TRUE)
1045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic void l2c_fcr_collect_ack_delay (tL2C_CCB *p_ccb, UINT8 num_bufs_acked);
1055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
1065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
1095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function         l2c_fcr_updcrc
1105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
1115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description      This function computes the CRC using the look-up table.
1125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
1135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns          CRC
1145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
1155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
1165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectunsigned short l2c_fcr_updcrc(unsigned short icrc, unsigned char *icp, int icnt)
1175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
1185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    register unsigned short crc = icrc;
1195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    register unsigned char  *cp = icp;
1205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    register          int   cnt = icnt;
1215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    while (cnt--)
1235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
1245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        crc = ((crc >> 8) & 0xff) ^ crctab[(crc & 0xff) ^ *cp++];
1255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
1265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return(crc);
1285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
1295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
1335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function         l2c_fcr_tx_get_fcs
1345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
1355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description      This function computes the CRC for a frame to be TXed.
1365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
1375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns          CRC
1385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
1395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
1405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source ProjectUINT16 l2c_fcr_tx_get_fcs (BT_HDR *p_buf)
1415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
1425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    UINT8   *p = ((UINT8 *) (p_buf + 1)) + p_buf->offset;
1435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return (l2c_fcr_updcrc (L2CAP_FCR_INIT_CRC, p, p_buf->len));
1455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
1465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
1495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function         l2c_fcr_rx_get_fcs
1505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
1515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description      This function computes the CRC for a received frame.
1525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
1535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns          CRC
1545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
1555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
1565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source ProjectUINT16 l2c_fcr_rx_get_fcs (BT_HDR *p_buf)
1575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
1585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    UINT8   *p = ((UINT8 *) (p_buf + 1)) + p_buf->offset;
1595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* offset points past the L2CAP header, but the CRC check includes it */
1615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p -= L2CAP_PKT_OVERHEAD;
1625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return (l2c_fcr_updcrc (L2CAP_FCR_INIT_CRC, p, p_buf->len + L2CAP_PKT_OVERHEAD));
1645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
1655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
1685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function         l2c_fcr_start_timer
1695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
1705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description      This function starts the (monitor or retransmission) timer.
1715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
1725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns          -
1735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
1745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
1755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectvoid l2c_fcr_start_timer (tL2C_CCB *p_ccb)
1765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
1775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    UINT32  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    {
1825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        tout = (UINT32)p_ccb->our_cfg.fcr.mon_tout;
1835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
1845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    else
1855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
1865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        tout = (UINT32)p_ccb->our_cfg.fcr.rtrans_tout;
1875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
1885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*
189a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati    L2CAP_TRACE_DEBUG ("l2c_fcr_start_timer Tout: %u  Already Running: %u  wait_ack: %u  ack_q_count: %u",
1905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                        tout, p_ccb->timer_entry.in_use, p_ccb->fcrb.wait_ack, p_ccb->fcrb.waiting_for_ack_q.count);
1915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*/
1925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Only start a timer that was not started */
1935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (p_ccb->fcrb.mon_retrans_timer.in_use == 0)
1945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        btu_start_quick_timer (&p_ccb->fcrb.mon_retrans_timer, BTU_TTYPE_L2CAP_CHNL, tout*QUICK_TIMER_TICKS_PER_SEC/1000);
1955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
1965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
1995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function         l2c_fcr_stop_timer
2005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
2015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description      This function stops the (monitor or transmission) timer.
2025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
2035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns          -
2045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
2055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
2065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectvoid l2c_fcr_stop_timer (tL2C_CCB *p_ccb)
2075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
2085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (p_ccb->fcrb.mon_retrans_timer.in_use)
2095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
2105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*
211a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati        L2CAP_TRACE_DEBUG ("l2c_fcr_stop_timer wait_ack: %u  ack_q_count: %u",
2125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                            p_ccb->fcrb.wait_ack, p_ccb->fcrb.waiting_for_ack_q.count);
2135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*/
2145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        btu_stop_quick_timer (&p_ccb->fcrb.mon_retrans_timer);
2155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
2165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
2175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
2205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function         l2c_fcr_cleanup
2215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
2225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description      This function cleans up the variable used for flow-control/retrans.
2235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
2245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns          -
2255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
2265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
2275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectvoid l2c_fcr_cleanup (tL2C_CCB *p_ccb)
2285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
2295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    tL2C_FCRB *p_fcrb = &p_ccb->fcrb;
2305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    l2c_fcr_stop_timer (p_ccb);
2325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (p_fcrb->p_rx_sdu)
2345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        GKI_freebuf (p_fcrb->p_rx_sdu);
2355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    while (p_fcrb->waiting_for_ack_q.p_first)
2375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        GKI_freebuf (GKI_dequeue (&p_fcrb->waiting_for_ack_q));
2385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    while (p_fcrb->srej_rcv_hold_q.p_first)
2405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        GKI_freebuf (GKI_dequeue (&p_fcrb->srej_rcv_hold_q));
2415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    while (p_fcrb->retrans_q.p_first)
2435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        GKI_freebuf (GKI_dequeue (&p_fcrb->retrans_q));
2445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    btu_stop_quick_timer (&p_fcrb->ack_timer);
2465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    btu_stop_quick_timer (&p_ccb->fcrb.mon_retrans_timer);
2475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ERTM_STATS == TRUE)
2495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if ( (p_ccb->local_cid >= L2CAP_BASE_APPL_CID) && (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) )
2505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
2515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        UINT32  dur = GKI_get_os_tick_count() - p_ccb->fcrb.connect_tick_count;
2525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        char    *p_str = (char *)GKI_getbuf(120);
2535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        UINT16  i;
2545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        UINT32  throughput_avg, ack_delay_avg, ack_q_count_avg;
2555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        dur = GKI_OS_TICKS_TO_MS(dur);
2570212487880be33e255d49f6e38dbb035d1f77750Sharvil Nanavati        BT_TRACE(TRACE_CTRL_GENERAL | TRACE_LAYER_GKI | TRACE_ORG_GKI , TRACE_TYPE_GENERIC,
2585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                   "---  L2CAP ERTM  Stats for CID: 0x%04x   Duration: %08ums", p_ccb->local_cid, dur);
2590212487880be33e255d49f6e38dbb035d1f77750Sharvil Nanavati        BT_TRACE(TRACE_CTRL_GENERAL | TRACE_LAYER_GKI | TRACE_ORG_GKI , TRACE_TYPE_GENERIC,
2605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                   "Retransmissions:%08u Times Flow Controlled:%08u Retrans Touts:%08u Ack Touts:%08u",
2615738f83aeb59361a0a2eda2460113f6dc919427The 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);
2620212487880be33e255d49f6e38dbb035d1f77750Sharvil Nanavati        BT_TRACE(TRACE_CTRL_GENERAL | TRACE_LAYER_GKI | TRACE_ORG_GKI , TRACE_TYPE_GENERIC,
2635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                   "Times there is less than 2 packets in controller when flow controlled:%08u", p_ccb->fcrb.controller_idle);
2640212487880be33e255d49f6e38dbb035d1f77750Sharvil Nanavati        BT_TRACE(TRACE_CTRL_GENERAL | TRACE_LAYER_GKI | TRACE_ORG_GKI , TRACE_TYPE_GENERIC,
2655738f83aeb59361a0a2eda2460113f6dc919427The 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 );
2665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (p_str)
2675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
2685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            sprintf(p_str, "Sent Pkts:%08u Bytes:%10u(%06u/sec) RR:%08u REJ:%08u RNR:%08u SREJ:%08u",
2695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                p_ccb->fcrb.ertm_pkt_counts[0], p_ccb->fcrb.ertm_byte_counts[0],
2705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                (dur >= 10 ? (p_ccb->fcrb.ertm_byte_counts[0] * 100) / (dur / 10) : 0),
2715738f83aeb59361a0a2eda2460113f6dc919427The 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]);
2725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2730212487880be33e255d49f6e38dbb035d1f77750Sharvil Nanavati            BT_TRACE(TRACE_CTRL_GENERAL | TRACE_LAYER_GKI | TRACE_ORG_GKI , TRACE_TYPE_GENERIC, "%s", p_str);
2745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            sprintf(p_str, "Rcvd Pkts:%08u Bytes:%10u(%06u/sec) RR:%08u REJ:%08u RNR:%08u SREJ:%08u",
2765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                p_ccb->fcrb.ertm_pkt_counts[1], p_ccb->fcrb.ertm_byte_counts[1],
2775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                (dur >= 10 ? (p_ccb->fcrb.ertm_byte_counts[1] * 100) / (dur / 10) : 0),
2785738f83aeb59361a0a2eda2460113f6dc919427The 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]);
2795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2800212487880be33e255d49f6e38dbb035d1f77750Sharvil Nanavati            BT_TRACE(TRACE_CTRL_GENERAL | TRACE_LAYER_GKI | TRACE_ORG_GKI , TRACE_TYPE_GENERIC, "%s", p_str);
2815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            throughput_avg  = 0;
2835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            ack_delay_avg   = 0;
2845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            ack_q_count_avg = 0;
2855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            for (i = 0; i < L2CAP_ERTM_STATS_NUM_AVG; i++ )
2875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
2885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                if (i == p_ccb->fcrb.ack_delay_avg_index )
2895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                {
2900212487880be33e255d49f6e38dbb035d1f77750Sharvil Nanavati                    BT_TRACE(TRACE_CTRL_GENERAL | TRACE_LAYER_GKI | TRACE_ORG_GKI , TRACE_TYPE_GENERIC,
2915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                           "[%02u] collecting data ...", i );
2925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    continue;
2935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                }
2945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                sprintf(p_str, "[%02u] throughput: %5u, ack_delay avg:%3u, min:%3u, max:%3u, ack_q_count avg:%3u, min:%3u, max:%3u",
2965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                        i, p_ccb->fcrb.throughput[i],
2975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                        p_ccb->fcrb.ack_delay_avg[i], p_ccb->fcrb.ack_delay_min[i], p_ccb->fcrb.ack_delay_max[i],
2985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                        p_ccb->fcrb.ack_q_count_avg[i], p_ccb->fcrb.ack_q_count_min[i], p_ccb->fcrb.ack_q_count_max[i] );
2995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3000212487880be33e255d49f6e38dbb035d1f77750Sharvil Nanavati                BT_TRACE(TRACE_CTRL_GENERAL | TRACE_LAYER_GKI | TRACE_ORG_GKI , TRACE_TYPE_GENERIC, "%s", p_str);
3015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                throughput_avg  += p_ccb->fcrb.throughput[i];
3035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                ack_delay_avg   += p_ccb->fcrb.ack_delay_avg[i];
3045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                ack_q_count_avg += p_ccb->fcrb.ack_q_count_avg[i];
3055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
3065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            throughput_avg  /= (L2CAP_ERTM_STATS_NUM_AVG - 1);
3085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            ack_delay_avg   /= (L2CAP_ERTM_STATS_NUM_AVG - 1);
3095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            ack_q_count_avg /= (L2CAP_ERTM_STATS_NUM_AVG - 1);
3105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3110212487880be33e255d49f6e38dbb035d1f77750Sharvil Nanavati            BT_TRACE(TRACE_CTRL_GENERAL | TRACE_LAYER_GKI | TRACE_ORG_GKI , TRACE_TYPE_GENERIC,
3125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                   "throughput_avg: %8u (kbytes/sec), ack_delay_avg: %8u ms, ack_q_count_avg: %8u",
3135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    throughput_avg, ack_delay_avg, ack_q_count_avg );
3145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            GKI_freebuf(p_str);
3165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
3175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3180212487880be33e255d49f6e38dbb035d1f77750Sharvil Nanavati        BT_TRACE(TRACE_CTRL_GENERAL | TRACE_LAYER_GKI | TRACE_ORG_GKI , TRACE_TYPE_GENERIC,
3195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                   "---");
3205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
3215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
3225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    memset (p_fcrb, 0, sizeof (tL2C_FCRB));
3245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
3255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
3275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
3285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function         l2c_fcr_clone_buf
3295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
3305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description      This function allocates and copies requested part of a buffer
3315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  at a new-offset.
3325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
3335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns          pointer to new buffer
3345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
3355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
3365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source ProjectBT_HDR *l2c_fcr_clone_buf (BT_HDR *p_buf, UINT16 new_offset, UINT16 no_of_bytes, UINT8 pool)
3375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
3385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    BT_HDR *p_buf2;
3395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* If using the common pool, should be at least 10% free. */
3415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if ( (pool == HCI_ACL_POOL_ID) && (GKI_poolutilization (pool) > 90) )
3425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
343a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati        L2CAP_TRACE_ERROR ("L2CAP - failed to clone buffer on HCI_ACL_POOL_ID Utilization: %u", GKI_poolutilization(pool));
3445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        return (NULL);
3455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
3465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if ((p_buf2 = (BT_HDR *)GKI_getpoolbuf(pool)) != NULL)
3485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
3495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        UINT16    pool_buf_size = GKI_get_pool_bufsize (pool);
3505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* Make sure buffer fits into buffer pool */
3525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if ((no_of_bytes + sizeof(BT_HDR) + new_offset) > pool_buf_size)
3535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
354a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati            L2CAP_TRACE_ERROR("##### l2c_fcr_clone_buf (NumBytes %d) -> Exceeds poolsize %d [bytes %d + BT_HDR %d + offset %d]",
3555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                               (no_of_bytes + sizeof(BT_HDR) + new_offset),
3565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                               pool_buf_size, no_of_bytes, sizeof(BT_HDR),
3575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                               new_offset);
3585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            GKI_freebuf(p_buf2);
3605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            return (NULL);
3615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
3625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_buf2->offset = new_offset;
3645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_buf2->len    = no_of_bytes;
3655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        memcpy (((UINT8 *)(p_buf2 + 1)) + p_buf2->offset,
3675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                ((UINT8 *)(p_buf + 1))  + p_buf->offset,
3685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                no_of_bytes);
3695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
3705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    else
3715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
372a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati        L2CAP_TRACE_ERROR ("L2CAP - failed to clone buffer, Pool: %u  Count: %u", pool,  GKI_poolfreecount(pool));
3735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
3745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return (p_buf2);
3765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
3775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
3795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
3805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function         l2c_fcr_is_flow_controlled
3815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
3825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description      This function checks if the CCB is flow controlled by peer.
3835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
3845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns          The control word
3855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
3865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
3875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source ProjectBOOLEAN l2c_fcr_is_flow_controlled (tL2C_CCB *p_ccb)
3885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
3895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE)
3905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
3915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* Check if remote side flowed us off or the transmit window is full */
3925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if ( (p_ccb->fcrb.remote_busy == TRUE)
3935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project         ||  (p_ccb->fcrb.waiting_for_ack_q.count >= p_ccb->peer_cfg.fcr.tx_win_sz) )
3945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
3955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ERTM_STATS == TRUE)
3965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if (p_ccb->xmit_hold_q.count != 0)
3975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
3985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                p_ccb->fcrb.xmit_window_closed++;
3995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                if ((p_ccb->p_lcb->sent_not_acked < 2)&&(l2cb.controller_xmit_window > 0))
4015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    p_ccb->fcrb.controller_idle++;
4025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
4035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
4045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            return (TRUE);
4055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
4065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
4075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return (FALSE);
4085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
4095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
4115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
4125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function         prepare_I_frame
4135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
4145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description      This function sets the FCR variables in an I-frame that is
4155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  about to be sent to HCI for transmission. This may be the
4165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  first time the I-frame is sent, or a retransmission
4175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
4185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns          -
4195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
4205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
4215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic void prepare_I_frame (tL2C_CCB *p_ccb, BT_HDR *p_buf, BOOLEAN is_retransmission)
4225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
4235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    tL2C_FCRB   *p_fcrb = &p_ccb->fcrb;
4245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    UINT8       *p;
4255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    UINT16      fcs;
4265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    UINT16      ctrl_word;
4275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    BOOLEAN     set_f_bit = p_fcrb->send_f_rsp;
4285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p_fcrb->send_f_rsp = FALSE;
4305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (is_retransmission)
4325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
4335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* Get the old control word and clear out the old req_seq and F bits */
4345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p = ((UINT8 *) (p_buf+1)) + p_buf->offset + L2CAP_PKT_OVERHEAD;
4355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        STREAM_TO_UINT16 (ctrl_word, p);
4375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        ctrl_word  &= ~(L2CAP_FCR_REQ_SEQ_BITS + L2CAP_FCR_F_BIT);
4395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
4405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    else
4415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
4425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        ctrl_word  = p_buf->layer_specific & L2CAP_FCR_SEG_BITS;                /* SAR bits */
4435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        ctrl_word |= (p_fcrb->next_tx_seq << L2CAP_FCR_TX_SEQ_BITS_SHIFT);      /* Tx Seq */
4445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_fcrb->next_tx_seq = (p_fcrb->next_tx_seq + 1) & L2CAP_FCR_SEQ_MODULO;
4465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
4475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Set the F-bit and reqseq only if using re-transmission mode */
4495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE)
4505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
4515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (set_f_bit)
4525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            ctrl_word |= L2CAP_FCR_F_BIT;
4535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        ctrl_word |= (p_fcrb->next_seq_expected) << L2CAP_FCR_REQ_SEQ_BITS_SHIFT;
4555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_fcrb->last_ack_sent = p_ccb->fcrb.next_seq_expected;
4575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (p_ccb->fcrb.ack_timer.in_use)
4595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            btu_stop_quick_timer (&p_ccb->fcrb.ack_timer);
4605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
4615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Set the control word */
4635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p = ((UINT8 *) (p_buf+1)) + p_buf->offset + L2CAP_PKT_OVERHEAD;
4645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    UINT16_TO_STREAM (p, ctrl_word);
4665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Compute the FCS and add to the end of the buffer if not bypassed */
4685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (p_ccb->bypass_fcs != L2CAP_BYPASS_FCS)
4695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
4705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* length field in l2cap header has to include FCS length */
4715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p = ((UINT8 *) (p_buf+1)) + p_buf->offset;
4725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        UINT16_TO_STREAM (p, p_buf->len + L2CAP_FCS_LEN - L2CAP_PKT_OVERHEAD);
4735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* Calculate the FCS */
4755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        fcs = l2c_fcr_tx_get_fcs(p_buf);
4765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* Point to the end of the buffer and put the FCS there */
4785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p = ((UINT8 *) (p_buf+1)) + p_buf->offset + p_buf->len;
4795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        UINT16_TO_STREAM (p, fcs);
4815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_buf->len += L2CAP_FCS_LEN;
4835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
4845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if BT_TRACE_VERBOSE == TRUE
4865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (is_retransmission)
4875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
488a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati        L2CAP_TRACE_EVENT ("L2CAP eRTM ReTx I-frame  CID: 0x%04x  Len: %u  SAR: %s  TxSeq: %u  ReqSeq: %u  F: %u",
4895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                            p_ccb->local_cid, p_buf->len,
4905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                            SAR_types[(ctrl_word & L2CAP_FCR_SAR_BITS) >> L2CAP_FCR_SAR_BITS_SHIFT],
4915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                            (ctrl_word & L2CAP_FCR_TX_SEQ_BITS) >> L2CAP_FCR_TX_SEQ_BITS_SHIFT,
4925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                            (ctrl_word & L2CAP_FCR_REQ_SEQ_BITS) >> L2CAP_FCR_REQ_SEQ_BITS_SHIFT,
4935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                            (ctrl_word & L2CAP_FCR_F_BIT) >> L2CAP_FCR_F_BIT_SHIFT);
4945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
4955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    else
4965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
497a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati        L2CAP_TRACE_EVENT ("L2CAP eRTM Tx I-frame CID: 0x%04x  Len: %u  SAR: %-12s  TxSeq: %u  ReqSeq: %u  F: %u",
4985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                            p_ccb->local_cid, p_buf->len,
4995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                            SAR_types[(ctrl_word & L2CAP_FCR_SAR_BITS) >> L2CAP_FCR_SAR_BITS_SHIFT],
5005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                            (ctrl_word & L2CAP_FCR_TX_SEQ_BITS) >> L2CAP_FCR_TX_SEQ_BITS_SHIFT,
5015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                            (ctrl_word & L2CAP_FCR_REQ_SEQ_BITS) >> L2CAP_FCR_REQ_SEQ_BITS_SHIFT,
5025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                            (ctrl_word & L2CAP_FCR_F_BIT) >> L2CAP_FCR_F_BIT_SHIFT);
5035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
5045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
5055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Start the retransmission timer if not already running */
5075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE)
5085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        l2c_fcr_start_timer (p_ccb);
5095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
5105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
5125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
5135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function         l2c_fcr_send_S_frame
5145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
5155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description      This function formats and sends an S-frame for transmission.
5165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
5175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns          -
5185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
5195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
5205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectvoid l2c_fcr_send_S_frame (tL2C_CCB *p_ccb, UINT16 function_code, UINT16 pf_bit)
5215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
5225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    BT_HDR      *p_buf;
5235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    UINT8       *p;
5245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    UINT16      ctrl_word;
5255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    UINT16      fcs;
5265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if L2CAP_CORRUPT_ERTM_PKTS == TRUE
5285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Only used for conformance testing */
5295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (l2c_bypass_sframe_packet (p_ccb))
5305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        return;
5315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
5325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if ((!p_ccb->in_use) || (p_ccb->chnl_state != CST_OPEN))
5345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        return;
5355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ERTM_STATS == TRUE)
5375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project     p_ccb->fcrb.s_frames_sent[function_code]++;
5385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
5395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (pf_bit == L2CAP_FCR_P_BIT)
5415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
5425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_ccb->fcrb.wait_ack = TRUE;
5435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        l2c_fcr_stop_timer (p_ccb);         /* Restart the monitor timer */
5455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        l2c_fcr_start_timer (p_ccb);
5465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
5475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Create the control word to use */
5495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    ctrl_word = (function_code << L2CAP_FCR_SUP_SHIFT) | L2CAP_FCR_S_FRAME_BIT;
5505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    ctrl_word |= (p_ccb->fcrb.next_seq_expected << L2CAP_FCR_REQ_SEQ_BITS_SHIFT);
5515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    ctrl_word |= pf_bit;
5525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if ((p_buf = (BT_HDR *)GKI_getpoolbuf (L2CAP_CMD_POOL_ID)) != NULL)
5545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
5555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_buf->offset = HCI_DATA_PREAMBLE_SIZE;
5565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_buf->len    = L2CAP_PKT_OVERHEAD + L2CAP_FCR_OVERHEAD;
5575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* Set the pointer to the beginning of the data */
5595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p = (UINT8 *)(p_buf + 1) + p_buf->offset;
5605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* Put in the L2CAP header */
5625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        UINT16_TO_STREAM (p, L2CAP_FCR_OVERHEAD + L2CAP_FCS_LEN);
5635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        UINT16_TO_STREAM (p, p_ccb->remote_cid);
5645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        UINT16_TO_STREAM (p, ctrl_word);
5655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* Compute the FCS and add to the end of the buffer if not bypassed */
5675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (p_ccb->bypass_fcs != L2CAP_BYPASS_FCS)
5685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
5695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            fcs = l2c_fcr_tx_get_fcs (p_buf);
5705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            UINT16_TO_STREAM (p, fcs);
5725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_buf->len += L2CAP_FCS_LEN;
5735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
5745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        else /* rewrite the length without FCS length */
5755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
5765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p -= 6;
5775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            UINT16_TO_STREAM (p, L2CAP_FCR_OVERHEAD);
5785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
5795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if L2CAP_CORRUPT_ERTM_PKTS == TRUE
5815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* Get out if packet was dropped */
5825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (l2c_corrupt_the_fcr_packet (p_ccb, p_buf, FALSE, ctrl_word))
5835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            return;
5845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
5855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* Now, the HCI transport header */
5865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_buf->layer_specific = L2CAP_NON_FLUSHABLE_PKT;
5875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        l2cu_set_acl_hci_header (p_buf, p_ccb);
5885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if BT_TRACE_VERBOSE == TRUE
5905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if ((((ctrl_word & L2CAP_FCR_SUP_BITS) >> L2CAP_FCR_SUP_SHIFT) == 1)
5915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project         || (((ctrl_word & L2CAP_FCR_SUP_BITS) >> L2CAP_FCR_SUP_SHIFT) == 3))
5925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
593a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati            L2CAP_TRACE_WARNING ("L2CAP eRTM Tx S-frame  CID: 0x%04x  ctrlword: 0x%04x  Type: %s  ReqSeq: %u  P: %u  F: %u",
5945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                            p_ccb->local_cid, ctrl_word,
5955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                            SUP_types[(ctrl_word & L2CAP_FCR_SUP_BITS) >> L2CAP_FCR_SUP_SHIFT],
5965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                            (ctrl_word & L2CAP_FCR_REQ_SEQ_BITS) >> L2CAP_FCR_REQ_SEQ_BITS_SHIFT,
5975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                            (ctrl_word & L2CAP_FCR_P_BIT) >> L2CAP_FCR_P_BIT_SHIFT,
5985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                            (ctrl_word & L2CAP_FCR_F_BIT) >> L2CAP_FCR_F_BIT_SHIFT);
599a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati            L2CAP_TRACE_WARNING ("                  Buf Len: %u", p_buf->len);
6005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
6015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        else
6025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
603a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati            L2CAP_TRACE_EVENT ("L2CAP eRTM Tx S-frame  CID: 0x%04x  ctrlword: 0x%04x  Type: %s  ReqSeq: %u  P: %u  F: %u",
6045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                            p_ccb->local_cid, ctrl_word,
6055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                            SUP_types[(ctrl_word & L2CAP_FCR_SUP_BITS) >> L2CAP_FCR_SUP_SHIFT],
6065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                            (ctrl_word & L2CAP_FCR_REQ_SEQ_BITS) >> L2CAP_FCR_REQ_SEQ_BITS_SHIFT,
6075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                            (ctrl_word & L2CAP_FCR_P_BIT) >> L2CAP_FCR_P_BIT_SHIFT,
6085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                            (ctrl_word & L2CAP_FCR_F_BIT) >> L2CAP_FCR_F_BIT_SHIFT);
609a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati            L2CAP_TRACE_EVENT ("                  Buf Len: %u", p_buf->len);
6105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
6115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif  /* BT_TRACE_VERBOSE */
6125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
6135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, p_buf);
6145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
6155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_ccb->fcrb.last_ack_sent = p_ccb->fcrb.next_seq_expected;
6165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
6175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (p_ccb->fcrb.ack_timer.in_use)
6185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            btu_stop_quick_timer (&p_ccb->fcrb.ack_timer);
6195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
6205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    else
6215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
622a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati        L2CAP_TRACE_ERROR ("l2c_fcr_send_S_frame(No Resources) cid 0x%04x, Type: 0x%4x",
6235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                             p_ccb->local_cid, function_code);
6245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
6255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
6265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
6275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
6285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
6295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
6305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function         l2c_fcr_proc_pdu
6315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
6325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description      This function is the entry point for processing of a
6335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  received PDU when in flow control and/or retransmission modes.
6345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
6355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns          -
6365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
6375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
6385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectvoid l2c_fcr_proc_pdu (tL2C_CCB *p_ccb, BT_HDR *p_buf)
6395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
6405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    UINT8       *p;
6415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    UINT16      fcs;
6425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    UINT16      min_pdu_len;
6435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    UINT16      ctrl_word;
6445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
6455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Check the length */
6465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    min_pdu_len = (p_ccb->bypass_fcs == L2CAP_BYPASS_FCS) ?
6475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                  (UINT16)L2CAP_FCR_OVERHEAD : (UINT16)(L2CAP_FCS_LEN + L2CAP_FCR_OVERHEAD);
6485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
6495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (p_buf->len < min_pdu_len)
6505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
651a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati        L2CAP_TRACE_WARNING ("Rx L2CAP PDU: CID: 0x%04x  Len too short: %u", p_ccb->local_cid, p_buf->len);
6525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        GKI_freebuf (p_buf);
6535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        return;
6545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
6555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
6565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_STREAM_MODE)
6575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
6585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        process_stream_frame (p_ccb, p_buf);
6595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        return;
6605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
6615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
6625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if BT_TRACE_VERBOSE == TRUE
6635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Get the control word */
6645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p = ((UINT8 *)(p_buf+1)) + p_buf->offset;
6655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    STREAM_TO_UINT16 (ctrl_word, p);
6665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
6675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (ctrl_word & L2CAP_FCR_S_FRAME_BIT)
6685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
6695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if ((((ctrl_word & L2CAP_FCR_SUP_BITS) >> L2CAP_FCR_SUP_SHIFT) == 1)
6705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project         || (((ctrl_word & L2CAP_FCR_SUP_BITS) >> L2CAP_FCR_SUP_SHIFT) == 3))
6715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
6725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* REJ or SREJ */
673a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati            L2CAP_TRACE_WARNING ("L2CAP eRTM Rx S-frame: cid: 0x%04x  Len: %u  Type: %s  ReqSeq: %u  P: %u  F: %u",
6745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                            p_ccb->local_cid, p_buf->len,
6755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                            SUP_types[(ctrl_word & L2CAP_FCR_SUP_BITS) >> L2CAP_FCR_SUP_SHIFT],
6765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                            (ctrl_word & L2CAP_FCR_REQ_SEQ_BITS) >> L2CAP_FCR_REQ_SEQ_BITS_SHIFT,
6775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                            (ctrl_word & L2CAP_FCR_P_BIT) >> L2CAP_FCR_P_BIT_SHIFT,
6785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                            (ctrl_word & L2CAP_FCR_F_BIT) >> L2CAP_FCR_F_BIT_SHIFT);
6795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
6805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        else
6815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
682a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati            L2CAP_TRACE_EVENT ("L2CAP eRTM Rx S-frame: cid: 0x%04x  Len: %u  Type: %s  ReqSeq: %u  P: %u  F: %u",
6835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                            p_ccb->local_cid, p_buf->len,
6845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                            SUP_types[(ctrl_word & L2CAP_FCR_SUP_BITS) >> L2CAP_FCR_SUP_SHIFT],
6855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                            (ctrl_word & L2CAP_FCR_REQ_SEQ_BITS) >> L2CAP_FCR_REQ_SEQ_BITS_SHIFT,
6865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                            (ctrl_word & L2CAP_FCR_P_BIT) >> L2CAP_FCR_P_BIT_SHIFT,
6875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                            (ctrl_word & L2CAP_FCR_F_BIT) >> L2CAP_FCR_F_BIT_SHIFT);
6885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
6895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
6905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    else
6915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
692a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati        L2CAP_TRACE_EVENT ("L2CAP eRTM Rx I-frame: cid: 0x%04x  Len: %u  SAR: %-12s  TxSeq: %u  ReqSeq: %u  F: %u",
6935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                            p_ccb->local_cid, p_buf->len,
6945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                            SAR_types[(ctrl_word & L2CAP_FCR_SAR_BITS) >> L2CAP_FCR_SAR_BITS_SHIFT],
6955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                            (ctrl_word & L2CAP_FCR_TX_SEQ_BITS) >> L2CAP_FCR_TX_SEQ_BITS_SHIFT,
6965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                            (ctrl_word & L2CAP_FCR_REQ_SEQ_BITS) >> L2CAP_FCR_REQ_SEQ_BITS_SHIFT,
6975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                            (ctrl_word & L2CAP_FCR_F_BIT) >> L2CAP_FCR_F_BIT_SHIFT);
6985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
6995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
700a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil 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",
7015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                        p_ccb->fcrb.next_tx_seq, p_ccb->fcrb.last_rx_ack, p_ccb->fcrb.next_seq_expected,
7025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                        p_ccb->fcrb.last_ack_sent, p_ccb->fcrb.waiting_for_ack_q.count, p_ccb->fcrb.num_tries);
7035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif /* BT_TRACE_VERBOSE */
7055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if L2CAP_CORRUPT_ERTM_PKTS == TRUE
7075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p = ((UINT8 *)(p_buf+1)) + p_buf->offset;
7085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    STREAM_TO_UINT16 (ctrl_word, p);
7095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Get out if packet was dropped */
7115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (l2c_corrupt_the_fcr_packet (p_ccb, p_buf, TRUE, ctrl_word))
7125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        return;
7135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif  /* L2CAP_CORRUPT_ERTM_PKTS */
7145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Verify FCS if using */
7165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (p_ccb->bypass_fcs != L2CAP_BYPASS_FCS)
7175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
7185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p = ((UINT8 *)(p_buf+1)) + p_buf->offset + p_buf->len - L2CAP_FCS_LEN;
7195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* Extract and drop the FCS from the packet */
7215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        STREAM_TO_UINT16 (fcs, p);
7225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_buf->len -= L2CAP_FCS_LEN;
7235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (l2c_fcr_rx_get_fcs(p_buf) != fcs)
7255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
726a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati            L2CAP_TRACE_WARNING ("Rx L2CAP PDU: CID: 0x%04x  BAD FCS", p_ccb->local_cid);
7275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            GKI_freebuf(p_buf);
7285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            return;
7295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
7305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
7315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Get the control word */
7335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p = ((UINT8 *)(p_buf+1)) + p_buf->offset;
7345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    STREAM_TO_UINT16 (ctrl_word, p);
7365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p_buf->len    -= L2CAP_FCR_OVERHEAD;
7385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p_buf->offset += L2CAP_FCR_OVERHEAD;
7395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* If we had a poll bit outstanding, check if we got a final response */
7415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (p_ccb->fcrb.wait_ack)
7425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
7435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* If final bit not set, ignore the frame unless it is a polled S-frame */
7445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if ( !(ctrl_word & L2CAP_FCR_F_BIT) )
7455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
7465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if ( (ctrl_word & L2CAP_FCR_P_BIT) && (ctrl_word & L2CAP_FCR_S_FRAME_BIT) )
7475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
7485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                if (p_ccb->fcrb.srej_sent)
7495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    l2c_fcr_send_S_frame (p_ccb, L2CAP_FCR_SUP_SREJ, L2CAP_FCR_F_BIT);
7505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                else if (p_ccb->fcrb.local_busy)
7515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    l2c_fcr_send_S_frame (p_ccb, L2CAP_FCR_SUP_RNR, L2CAP_FCR_F_BIT);
7525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                else
7535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    l2c_fcr_send_S_frame (p_ccb, L2CAP_FCR_SUP_RR, L2CAP_FCR_F_BIT);
7545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                /* Got a poll while in wait_ack state, so re-start our timer with 1-second */
7565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                /* This is a small optimization... the monitor timer is 12 secs, but we saw */
7575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                /* that if the other side sends us a poll when we are waiting for a final,  */
7585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                /* then it speeds up recovery significantly if we poll him back soon after his poll. */
7595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                btu_start_quick_timer (&p_ccb->fcrb.mon_retrans_timer, BTU_TTYPE_L2CAP_CHNL, QUICK_TIMER_TICKS_PER_SEC);
7605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
7615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            GKI_freebuf (p_buf);
7625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            return;
7635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
7645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_ccb->fcrb.wait_ack  = FALSE;
7665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* P and F are mutually exclusive */
7685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (ctrl_word & L2CAP_FCR_S_FRAME_BIT)
7695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            ctrl_word &= ~L2CAP_FCR_P_BIT;
7705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (p_ccb->fcrb.waiting_for_ack_q.count == 0)
7725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_ccb->fcrb.num_tries = 0;
7735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        l2c_fcr_stop_timer (p_ccb);
7755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
7765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    else
7775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
7785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* Otherwise, ensure the final bit is ignored */
7795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        ctrl_word &= ~L2CAP_FCR_F_BIT;
7805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
7815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Process receive sequence number */
7835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (!process_reqseq (p_ccb, ctrl_word))
7845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
7855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        GKI_freebuf (p_buf);
7865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        return;
7875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
7885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project     /* Process based on whether it is an S-frame or an I-frame */
7905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (ctrl_word & L2CAP_FCR_S_FRAME_BIT)
7915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        process_s_frame (p_ccb, p_buf, ctrl_word);
7925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    else
7935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        process_i_frame (p_ccb, p_buf, ctrl_word, FALSE);
7945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Return if the channel got disconnected by a bad packet or max retransmissions */
7965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if ( (!p_ccb->in_use) || (p_ccb->chnl_state != CST_OPEN) )
7975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        return;
7985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* If we have some buffers held while doing SREJ, and SREJ has cleared, process them now */
8005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if ( (!p_ccb->fcrb.local_busy) && (!p_ccb->fcrb.srej_sent) && (p_ccb->fcrb.srej_rcv_hold_q.count > 0) )
8015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
8025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        BUFFER_Q temp_q = p_ccb->fcrb.srej_rcv_hold_q;
8035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
8045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        GKI_init_q (&p_ccb->fcrb.srej_rcv_hold_q);
8055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
8065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        while ((p_buf = (BT_HDR *)GKI_dequeue (&temp_q)) != NULL)
8075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
8085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if (p_ccb->in_use && (p_ccb->chnl_state == CST_OPEN))
8095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
8105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                /* Get the control word */
8115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                p = ((UINT8 *)(p_buf+1)) + p_buf->offset - L2CAP_FCR_OVERHEAD;
8125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
8135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                STREAM_TO_UINT16 (ctrl_word, p);
8145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
815a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati                L2CAP_TRACE_DEBUG ("l2c_fcr_proc_pdu() CID: 0x%04x  Process Buffer from SREJ_Hold_Q   TxSeq: %u  Expected_Seq: %u",
8165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                                    p_ccb->local_cid, (ctrl_word & L2CAP_FCR_TX_SEQ_BITS) >> L2CAP_FCR_TX_SEQ_BITS_SHIFT,
8175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                                    p_ccb->fcrb.next_seq_expected);
8185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
8195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                /* Process the SREJ held I-frame, but do not send an RR for each individual frame */
8205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                process_i_frame (p_ccb, p_buf, ctrl_word, TRUE);
8215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
8225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            else
8235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                GKI_freebuf (p_buf);
8245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
8255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* If more frames were lost during SREJ, send a REJ */
8265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if (p_ccb->fcrb.rej_after_srej)
8275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
8285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                p_ccb->fcrb.rej_after_srej = FALSE;
8295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                p_ccb->fcrb.rej_sent       = TRUE;
8305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
8315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                l2c_fcr_send_S_frame (p_ccb, L2CAP_FCR_SUP_REJ, 0);
8325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
8335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
8345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
8355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* Now, if needed, send one RR for the whole held queue */
8365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if ( (!p_ccb->fcrb.local_busy) && (!p_ccb->fcrb.rej_sent) && (!p_ccb->fcrb.srej_sent)
8375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project         &&  (p_ccb->fcrb.next_seq_expected != p_ccb->fcrb.last_ack_sent) )
8385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            l2c_fcr_send_S_frame (p_ccb, L2CAP_FCR_SUP_RR, 0);
8395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        else
8405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
841a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil 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",
8425738f83aeb59361a0a2eda2460113f6dc919427The 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,
8435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                                p_ccb->fcrb.last_ack_sent);
8445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
8455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
8465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
8475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* If a window has opened, check if we can send any more packets */
8485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if ( (p_ccb->fcrb.retrans_q.count || p_ccb->xmit_hold_q.count)
8495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project      && (p_ccb->fcrb.wait_ack == FALSE)
8505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project      && (l2c_fcr_is_flow_controlled (p_ccb) == FALSE) )
8515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
8525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, NULL);
8535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
8545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
8555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
8565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
8575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
8585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function         l2c_fcr_proc_tout
8595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
8605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description      Handle a timeout. We should be in error recovery state.
8615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
8625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns          -
8635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
8645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
8655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectvoid l2c_fcr_proc_tout (tL2C_CCB *p_ccb)
8665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
867a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati    L2CAP_TRACE_DEBUG ("l2c_fcr_proc_tout:  CID: 0x%04x  num_tries: %u (max: %u)  wait_ack: %u  ack_q_count: %u",
8685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                        p_ccb->local_cid, p_ccb->fcrb.num_tries, p_ccb->peer_cfg.fcr.max_transmit,
8695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                        p_ccb->fcrb.wait_ack, p_ccb->fcrb.waiting_for_ack_q.count);
8705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
8715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ERTM_STATS == TRUE)
8725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p_ccb->fcrb.retrans_touts++;
8735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
8745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
8755738f83aeb59361a0a2eda2460113f6dc919427The 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) )
8765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
8775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        l2cu_disconnect_chnl (p_ccb);
8785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
8795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    else
8805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
8815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (!p_ccb->fcrb.srej_sent && !p_ccb->fcrb.rej_sent)
8825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
8835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if (p_ccb->fcrb.local_busy)
8845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                l2c_fcr_send_S_frame (p_ccb, L2CAP_FCR_SUP_RNR, L2CAP_FCR_P_BIT);
8855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            else
8865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                l2c_fcr_send_S_frame (p_ccb, L2CAP_FCR_SUP_RR, L2CAP_FCR_P_BIT);
8875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
8885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
8895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
8905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
8915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
8925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
8935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
8945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function         l2c_fcr_proc_ack_tout
8955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
8965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description      Send RR/RNR if we have not acked I frame
8975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
8985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns          -
8995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
9005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
9015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectvoid l2c_fcr_proc_ack_tout (tL2C_CCB *p_ccb)
9025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
903a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati    L2CAP_TRACE_DEBUG ("l2c_fcr_proc_ack_tout:  CID: 0x%04x State: %u  Wack:%u  Rq:%d  Acked:%d", p_ccb->local_cid,
9045738f83aeb59361a0a2eda2460113f6dc919427The 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);
9055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
9065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if ( (p_ccb->chnl_state == CST_OPEN) && (!p_ccb->fcrb.wait_ack)
9075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project      && (p_ccb->fcrb.last_ack_sent != p_ccb->fcrb.next_seq_expected) )
9085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
9095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ERTM_STATS == TRUE)
9105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_ccb->fcrb.xmit_ack_touts++;
9115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
9125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (p_ccb->fcrb.local_busy)
9135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            l2c_fcr_send_S_frame (p_ccb, L2CAP_FCR_SUP_RNR, 0);
9145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        else
9155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            l2c_fcr_send_S_frame (p_ccb, L2CAP_FCR_SUP_RR, 0);
9165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
9175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
9185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
9195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
9205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
9215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
9225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function         process_reqseq
9235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
9245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description      Handle receive sequence number
9255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
9265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns          -
9275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
9285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
9295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic BOOLEAN process_reqseq (tL2C_CCB *p_ccb, UINT16 ctrl_word)
9305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
9315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    tL2C_FCRB   *p_fcrb = &p_ccb->fcrb;
9325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    UINT8       req_seq, num_bufs_acked, xx;
9335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    UINT16      ls;
9345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    UINT16      full_sdus_xmitted;
9355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
9365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Receive sequence number does not ack anything for SREJ with P-bit set to zero */
9375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if ( (ctrl_word & L2CAP_FCR_S_FRAME_BIT)
9385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project     &&  ((ctrl_word & L2CAP_FCR_SUP_BITS) == (L2CAP_FCR_SUP_SREJ << L2CAP_FCR_SUP_SHIFT))
9395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project     &&  ((ctrl_word & L2CAP_FCR_P_BIT) == 0) )
9405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
9415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* If anything still waiting for ack, restart the timer if it was stopped */
9425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (p_fcrb->waiting_for_ack_q.count)
9435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            l2c_fcr_start_timer (p_ccb);
9445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
9455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        return (TRUE);
9465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
9475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
9485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Extract the receive sequence number from the control word */
9495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    req_seq = (ctrl_word & L2CAP_FCR_REQ_SEQ_BITS) >> L2CAP_FCR_REQ_SEQ_BITS_SHIFT;
9505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
9515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    num_bufs_acked = (req_seq - p_fcrb->last_rx_ack) & L2CAP_FCR_SEQ_MODULO;
9525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
9535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Verify the request sequence is in range before proceeding */
9545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (num_bufs_acked > p_fcrb->waiting_for_ack_q.count)
9555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
9565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* The channel is closed if ReqSeq is not in range */
957a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil 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",
9585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                               ctrl_word, req_seq, p_fcrb->last_rx_ack, p_fcrb->waiting_for_ack_q.count);
9595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
9605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        l2cu_disconnect_chnl (p_ccb);
9615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        return (FALSE);
9625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
9635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
9645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*
965a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati    L2CAP_TRACE_DEBUG ("L2CAP process_reqseq 0x%02x  last_rx_ack: 0x%02x  QCount: %u",
9665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                           req_seq, p_fcrb->last_rx_ack, p_fcrb->waiting_for_ack_q.count);
9675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*/
9685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p_fcrb->last_rx_ack = req_seq;
9695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
9705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Now we can release all acknowledged frames, and restart the retransmission timer if needed */
9715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (num_bufs_acked != 0)
9725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
9735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_fcrb->num_tries = 0;
9745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        full_sdus_xmitted = 0;
9755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
9765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ERTM_STATS == TRUE)
9775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        l2c_fcr_collect_ack_delay (p_ccb, num_bufs_acked);
9785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
9795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
9805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        for (xx = 0; xx < num_bufs_acked; xx++)
9815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
9825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            ls = ((BT_HDR *)(p_fcrb->waiting_for_ack_q.p_first))->layer_specific & L2CAP_FCR_SAR_BITS;
9835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
9845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if ( (ls == L2CAP_FCR_UNSEG_SDU) || (ls == L2CAP_FCR_END_SDU) )
9855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                full_sdus_xmitted++;
9865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
9875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            GKI_freebuf (GKI_dequeue (&p_fcrb->waiting_for_ack_q));
9885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
9895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
9905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* If we are still in a wait_ack state, do not mess with the timer */
9915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (!p_ccb->fcrb.wait_ack)
9925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            l2c_fcr_stop_timer (p_ccb);
9935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
9945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* Check if we need to call the "packet_sent" callback */
9955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if ( (p_ccb->p_rcb) && (p_ccb->p_rcb->api.pL2CA_TxComplete_Cb) && (full_sdus_xmitted) )
9965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
9975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* Special case for eRTM, if all packets sent, send 0xFFFF */
9985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if ( (p_fcrb->waiting_for_ack_q.count == 0) && (p_ccb->xmit_hold_q.count == 0) )
9995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                full_sdus_xmitted = 0xFFFF;
10005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
10015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            (*p_ccb->p_rcb->api.pL2CA_TxComplete_Cb)(p_ccb->local_cid, full_sdus_xmitted);
10025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
10035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
10045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
10055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* If anything still waiting for ack, restart the timer if it was stopped */
10065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (p_fcrb->waiting_for_ack_q.count)
10075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        l2c_fcr_start_timer (p_ccb);
10085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
10095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return (TRUE);
10105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
10115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
10125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
10135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
10145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
10155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function         process_s_frame
10165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
10175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description      Process an S frame
10185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
10195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns          -
10205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
10215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
10225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic void process_s_frame (tL2C_CCB *p_ccb, BT_HDR *p_buf, UINT16 ctrl_word)
10235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
10245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    tL2C_FCRB   *p_fcrb      = &p_ccb->fcrb;
10255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    UINT16      s_frame_type = (ctrl_word & L2CAP_FCR_SUP_BITS) >> L2CAP_FCR_SUP_SHIFT;
10265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    BOOLEAN     remote_was_busy;
10275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    BOOLEAN     all_ok = TRUE;
10285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
10295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (p_buf->len != 0)
10305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
1031a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati        L2CAP_TRACE_WARNING ("Incorrect S-frame Length (%d)", p_buf->len);
10325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
10335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1034a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati    L2CAP_TRACE_DEBUG ("process_s_frame ctrl_word 0x%04x fcrb_remote_busy:%d", ctrl_word, p_fcrb->remote_busy);
10355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
10365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ERTM_STATS == TRUE)
10375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p_ccb->fcrb.s_frames_rcvd[s_frame_type]++;
10385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
10395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
10405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (ctrl_word & L2CAP_FCR_P_BIT)
10415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
10425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_fcrb->rej_sent   = FALSE;             /* After checkpoint, we can send anoher REJ */
10435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_fcrb->send_f_rsp = TRUE;              /* Set a flag in case an I-frame is pending */
10445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
10455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
10465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    switch (s_frame_type)
10475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
10485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    case L2CAP_FCR_SUP_RR:
10495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        remote_was_busy     = p_fcrb->remote_busy;
10505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_fcrb->remote_busy = FALSE;
10515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
10525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if ( (ctrl_word & L2CAP_FCR_F_BIT) || (remote_was_busy) )
10535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            all_ok = retransmit_i_frames (p_ccb, L2C_FCR_RETX_ALL_PKTS);
10545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        break;
10555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
10565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    case L2CAP_FCR_SUP_REJ:
10575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_fcrb->remote_busy = FALSE;
10585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        all_ok = retransmit_i_frames (p_ccb, L2C_FCR_RETX_ALL_PKTS);
10595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        break;
10605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
10615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    case L2CAP_FCR_SUP_RNR:
10625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_fcrb->remote_busy = TRUE;
10635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        l2c_fcr_stop_timer (p_ccb);
10645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        break;
10655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
10665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    case L2CAP_FCR_SUP_SREJ:
10675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_fcrb->remote_busy = FALSE;
10685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        all_ok = retransmit_i_frames (p_ccb, (UINT8)((ctrl_word & L2CAP_FCR_REQ_SEQ_BITS) >> L2CAP_FCR_REQ_SEQ_BITS_SHIFT));
10695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        break;
10705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
10715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
10725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (all_ok)
10735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
10745738f83aeb59361a0a2eda2460113f6dc919427The 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 */
10755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (p_fcrb->send_f_rsp)
10765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
10775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if (p_fcrb->srej_sent)
10785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                l2c_fcr_send_S_frame (p_ccb, L2CAP_FCR_SUP_SREJ, L2CAP_FCR_F_BIT);
10795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            else if (p_fcrb->local_busy)
10805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                l2c_fcr_send_S_frame (p_ccb, L2CAP_FCR_SUP_RNR, L2CAP_FCR_F_BIT);
10815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            else
10825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                l2c_fcr_send_S_frame (p_ccb, L2CAP_FCR_SUP_RR, L2CAP_FCR_F_BIT);
10835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
10845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_fcrb->send_f_rsp = FALSE;
10855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
10865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
10875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    else
10885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
1089a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati        L2CAP_TRACE_DEBUG ("process_s_frame hit_max_retries");
10905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
10915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
10925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    GKI_freebuf (p_buf);
10935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
10945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
10955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
10965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
10975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
10985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function         process_i_frame
10995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
11005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description      Process an I frame
11015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
11025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns          -
11035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
11045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
11055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic void process_i_frame (tL2C_CCB *p_ccb, BT_HDR *p_buf, UINT16 ctrl_word, BOOLEAN delay_ack)
11065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
11075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    tL2C_FCRB   *p_fcrb = &p_ccb->fcrb;
11085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    UINT8       tx_seq, num_lost, num_to_ack, next_srej;
11095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
11105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* If we were doing checkpoint recovery, first retransmit all unacked I-frames */
11115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (ctrl_word & L2CAP_FCR_F_BIT)
11125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
11135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (!retransmit_i_frames (p_ccb, L2C_FCR_RETX_ALL_PKTS))
11145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
11155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            GKI_freebuf(p_buf);
11165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            return;
11175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
11185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
11195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
11205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ERTM_STATS == TRUE)
11215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p_ccb->fcrb.ertm_pkt_counts[1]++;
11225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p_ccb->fcrb.ertm_byte_counts[1] += p_buf->len;
11235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
11245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
11255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Extract the sequence number */
11265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    tx_seq = (ctrl_word & L2CAP_FCR_TX_SEQ_BITS) >> L2CAP_FCR_TX_SEQ_BITS_SHIFT;
11275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
11285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* If we have flow controlled the peer, ignore any bad I-frames from him */
11295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if ( (tx_seq != p_fcrb->next_seq_expected) && (p_fcrb->local_busy) )
11305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
1131a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati        L2CAP_TRACE_WARNING ("Dropping bad I-Frame since we flowed off, tx_seq:%u", tx_seq);
11325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        l2c_fcr_send_S_frame (p_ccb, L2CAP_FCR_SUP_RNR, 0);
11335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        GKI_freebuf(p_buf);
11345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        return;
11355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
11365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
11375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* If there are no free buffers in the user Rx queue, drop the  */
11385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* received buffer now before we update any sequence numbers    */
11395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (GKI_poolfreecount (p_ccb->ertm_info.user_rx_pool_id) == 0)
11405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
1141a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati        L2CAP_TRACE_WARNING ("L2CAP CID: 0x%04x  Dropping I-Frame seq: %u  User RX Pool: %u  (Size: %u)  has no free buffers!!",
11425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                              p_ccb->local_cid, tx_seq, p_ccb->ertm_info.user_rx_pool_id,
11435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                              GKI_poolcount (p_ccb->ertm_info.user_rx_pool_id));
11445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        GKI_freebuf(p_buf);
11455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        return;
11465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
11475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
11485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Check if tx-sequence is the expected one */
11495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (tx_seq != p_fcrb->next_seq_expected)
11505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
11515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        num_lost = (tx_seq - p_fcrb->next_seq_expected) & L2CAP_FCR_SEQ_MODULO;
11525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
11535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* Is the frame a duplicate ? If so, just drop it */
11545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (num_lost >= p_ccb->our_cfg.fcr.tx_win_sz)
11555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
11565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* Duplicate - simply drop it */
1157a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati            L2CAP_TRACE_WARNING ("process_i_frame() Dropping Duplicate Frame tx_seq:%u  ExpectedTxSeq %u", tx_seq, p_fcrb->next_seq_expected);
11585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            GKI_freebuf(p_buf);
11595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
11605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        else
11615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
1162a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati            L2CAP_TRACE_WARNING ("process_i_frame() CID: 0x%04x  Lost: %u  tx_seq:%u  ExpTxSeq %u  Rej: %u  SRej: %u",
11635738f83aeb59361a0a2eda2460113f6dc919427The 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);
11645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
11655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if (p_fcrb->srej_sent)
11665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
11675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                /* If SREJ sent, save the frame for later processing as long as it is in sequence */
11685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                next_srej = (((BT_HDR *)p_fcrb->srej_rcv_hold_q.p_last)->layer_specific + 1) & L2CAP_FCR_SEQ_MODULO;
11695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
11705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                if ( (tx_seq == next_srej) && (p_fcrb->srej_rcv_hold_q.count < p_ccb->our_cfg.fcr.tx_win_sz) )
11715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                {
11725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    /* If user gave us a pool for held rx buffers, use that */
11735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    if (p_ccb->ertm_info.fcr_rx_pool_id != HCI_ACL_POOL_ID)
11745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    {
11755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                        BT_HDR *p_buf2;
11765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
11775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                        /* Adjust offset and len so that control word is copied */
11785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                        p_buf->offset -= L2CAP_FCR_OVERHEAD;
11795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                        p_buf->len    += L2CAP_FCR_OVERHEAD;
11805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
11815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                        p_buf2 = l2c_fcr_clone_buf (p_buf, p_buf->offset, p_buf->len, p_ccb->ertm_info.fcr_rx_pool_id);
11825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
11835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                        if (p_buf2)
11845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                        {
11855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                            GKI_freebuf (p_buf);
11865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                            p_buf = p_buf2;
11875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                        }
11885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                        p_buf->offset += L2CAP_FCR_OVERHEAD;
11895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                        p_buf->len -= L2CAP_FCR_OVERHEAD;
11905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    }
1191a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati                    L2CAP_TRACE_DEBUG ("process_i_frame() Lost: %u  tx_seq:%u  ExpTxSeq %u  Rej: %u  SRej1",
11925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                                         num_lost, tx_seq, p_fcrb->next_seq_expected, p_fcrb->rej_sent);
11935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
11945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    p_buf->layer_specific = tx_seq;
11955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    GKI_enqueue (&p_fcrb->srej_rcv_hold_q, p_buf);
11965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                }
11975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                else
11985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                {
1199a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil 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",
12005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                                         p_ccb->local_cid, next_srej, p_fcrb->srej_rcv_hold_q.count, p_ccb->our_cfg.fcr.tx_win_sz);
12015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
12025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    p_fcrb->rej_after_srej = TRUE;
12035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    GKI_freebuf (p_buf);
12045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                }
12055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
12065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            else if (p_fcrb->rej_sent)
12075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
1208a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati                L2CAP_TRACE_WARNING ("process_i_frame() CID: 0x%04x  Lost: %u  tx_seq:%u  ExpTxSeq %u  Rej: 1  SRej: %u",
12095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                                     p_ccb->local_cid, num_lost, tx_seq, p_fcrb->next_seq_expected, p_fcrb->srej_sent);
12105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
12115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                /* If REJ sent, just drop the frame */
12125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                GKI_freebuf (p_buf);
12135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
12145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            else
12155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
1216a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati                L2CAP_TRACE_DEBUG ("process_i_frame() CID: 0x%04x  tx_seq:%u  ExpTxSeq %u  Rej: %u",
12175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                                     p_ccb->local_cid, tx_seq, p_fcrb->next_seq_expected, p_fcrb->rej_sent);
12185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
12195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                /* If only one lost, we will send SREJ, otherwise we will send REJ */
12205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                if (num_lost > 1)
12215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                {
12225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    GKI_freebuf (p_buf);
12235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    p_fcrb->rej_sent = TRUE;
12245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    l2c_fcr_send_S_frame (p_ccb, L2CAP_FCR_SUP_REJ, 0);
12255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                }
12265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                else
12275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                {
12285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    if (p_fcrb->srej_rcv_hold_q.count != 0)
12295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    {
1230a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati                        L2CAP_TRACE_ERROR ("process_i_frame() CID: 0x%04x  sending SREJ tx_seq:%d hold_q.count:%u",
12315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                                             p_ccb->local_cid, tx_seq, p_fcrb->srej_rcv_hold_q.count);
12325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    }
12335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    p_buf->layer_specific = tx_seq;
12345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    GKI_enqueue (&p_fcrb->srej_rcv_hold_q, p_buf);
12355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    p_fcrb->srej_sent = TRUE;
12365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    l2c_fcr_send_S_frame (p_ccb, L2CAP_FCR_SUP_SREJ, 0);
12375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                }
12385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                btu_stop_quick_timer (&p_ccb->fcrb.ack_timer);
12395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
12405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
12415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        return;
12425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
12435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
12445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Seq number is the next expected. Clear possible reject exception in case it occured */
12455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p_fcrb->rej_sent = p_fcrb->srej_sent = FALSE;
12465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
12475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Adjust the next_seq, so that if the upper layer sends more data in the callback
12485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project       context, the received frame is acked by an I-frame. */
12495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p_fcrb->next_seq_expected = (tx_seq + 1) & L2CAP_FCR_SEQ_MODULO;
12505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
12515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* If any SAR problem in eRTM mode, spec says disconnect. */
12525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (!do_sar_reassembly (p_ccb, p_buf, ctrl_word))
12535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
1254a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati        L2CAP_TRACE_WARNING ("process_i_frame() CID: 0x%04x  reassembly failed", p_ccb->local_cid);
12555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        l2cu_disconnect_chnl (p_ccb);
12565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        return;
12575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
12585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
12595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* RR optimization - if peer can still send us more, then start an ACK timer */
12605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    num_to_ack = (p_fcrb->next_seq_expected - p_fcrb->last_ack_sent) & L2CAP_FCR_SEQ_MODULO;
12615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
12625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if ( (num_to_ack < p_ccb->fcrb.max_held_acks) && (!p_fcrb->local_busy) )
12635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        delay_ack = TRUE;
12645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
12655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* We should neve never ack frame if we are not in OPEN state */
12665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if ((num_to_ack != 0) && p_ccb->in_use && (p_ccb->chnl_state == CST_OPEN))
12675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
12685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* If no frames are awaiting transmission or are held, send an RR or RNR S-frame for ack */
12695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (delay_ack)
12705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
12715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* If it is the first I frame we did not ack, start ack timer */
12725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if (!p_ccb->fcrb.ack_timer.in_use)
12735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
12745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                btu_start_quick_timer (&p_ccb->fcrb.ack_timer, BTU_TTYPE_L2CAP_FCR_ACK,
12755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                                        (L2CAP_FCR_ACK_TOUT*QUICK_TIMER_TICKS_PER_SEC)/1000);
12765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
12775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
12785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        else if ( ((p_ccb->xmit_hold_q.count == 0) || (l2c_fcr_is_flow_controlled (p_ccb)))
12795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project               &&  (p_ccb->fcrb.srej_rcv_hold_q.count == 0) )
12805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
12815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if (p_fcrb->local_busy)
12825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                l2c_fcr_send_S_frame (p_ccb, L2CAP_FCR_SUP_RNR, 0);
12835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            else
12845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                l2c_fcr_send_S_frame (p_ccb, L2CAP_FCR_SUP_RR, 0);
12855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
12865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
12875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
12885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
12895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
12905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
12915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
12925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function         process_stream_frame
12935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
12945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description      This function processes frames in streaming mode
12955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
12965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns          -
12975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
12985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
12995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic void process_stream_frame (tL2C_CCB *p_ccb, BT_HDR *p_buf)
13005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
13015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    UINT16      ctrl_word;
13025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    UINT16      fcs;
13035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    UINT8       *p;
13045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    UINT8       tx_seq;
13055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
13065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Verify FCS if using */
13075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (p_ccb->bypass_fcs != L2CAP_BYPASS_FCS)
13085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
13095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p = ((UINT8 *)(p_buf+1)) + p_buf->offset + p_buf->len - L2CAP_FCS_LEN;
13105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
13115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* Extract and drop the FCS from the packet */
13125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        STREAM_TO_UINT16 (fcs, p);
13135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_buf->len -= L2CAP_FCS_LEN;
13145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
13155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (l2c_fcr_rx_get_fcs(p_buf) != fcs)
13165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
1317a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati            L2CAP_TRACE_WARNING ("Rx L2CAP PDU: CID: 0x%04x  BAD FCS", p_ccb->local_cid);
13185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            GKI_freebuf(p_buf);
13195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            return;
13205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
13215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
13225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
13235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Get the control word */
13245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p = ((UINT8 *)(p_buf+1)) + p_buf->offset;
13255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
13265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    STREAM_TO_UINT16 (ctrl_word, p);
13275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
13285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p_buf->len    -= L2CAP_FCR_OVERHEAD;
13295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p_buf->offset += L2CAP_FCR_OVERHEAD;
13305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
13315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Make sure it is an I-frame */
13325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (ctrl_word & L2CAP_FCR_S_FRAME_BIT)
13335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
1334a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil 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);
13355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        GKI_freebuf (p_buf);
13365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        return;
13375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
13385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
13395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if BT_TRACE_VERBOSE == TRUE
1340a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati    L2CAP_TRACE_EVENT ("L2CAP eRTM Rx I-frame: cid: 0x%04x  Len: %u  SAR: %-12s  TxSeq: %u  ReqSeq: %u  F: %u",
13415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                        p_ccb->local_cid, p_buf->len,
13425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                        SAR_types[(ctrl_word & L2CAP_FCR_SAR_BITS) >> L2CAP_FCR_SAR_BITS_SHIFT],
13435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                        (ctrl_word & L2CAP_FCR_TX_SEQ_BITS) >> L2CAP_FCR_TX_SEQ_BITS_SHIFT,
13445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                        (ctrl_word & L2CAP_FCR_REQ_SEQ_BITS) >> L2CAP_FCR_REQ_SEQ_BITS_SHIFT,
13455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                        (ctrl_word & L2CAP_FCR_F_BIT) >> L2CAP_FCR_F_BIT_SHIFT);
13465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
13475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
13485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Extract the sequence number */
13495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    tx_seq = (ctrl_word & L2CAP_FCR_TX_SEQ_BITS) >> L2CAP_FCR_TX_SEQ_BITS_SHIFT;
13505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
13515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Check if tx-sequence is the expected one */
13525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (tx_seq != p_ccb->fcrb.next_seq_expected)
13535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
1354a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati        L2CAP_TRACE_WARNING ("Rx L2CAP PDU: CID: 0x%04x  Lost frames Exp: %u  Got: %u  p_rx_sdu: 0x%08x",
13555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                                p_ccb->local_cid, p_ccb->fcrb.next_seq_expected, tx_seq, p_ccb->fcrb.p_rx_sdu);
13565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
13575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* Lost one or more packets, so flush the SAR queue */
13585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (p_ccb->fcrb.p_rx_sdu != NULL)
13595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
13605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            GKI_freebuf (p_ccb->fcrb.p_rx_sdu);
13615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_ccb->fcrb.p_rx_sdu = NULL;
13625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
13635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
13645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
13655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p_ccb->fcrb.next_seq_expected = (tx_seq + 1) & L2CAP_FCR_SEQ_MODULO;
13665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
13675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (!do_sar_reassembly (p_ccb, p_buf, ctrl_word))
13685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
13695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* Some sort of SAR error, so flush the SAR queue */
13705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (p_ccb->fcrb.p_rx_sdu != NULL)
13715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
13725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            GKI_freebuf (p_ccb->fcrb.p_rx_sdu);
13735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_ccb->fcrb.p_rx_sdu = NULL;
13745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
13755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
13765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
13775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
13785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
13795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
13805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
13815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function         do_sar_reassembly
13825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
13835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description      Process SAR bits and re-assemble frame
13845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
13855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns          TRUE if all OK, else FALSE
13865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
13875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
13885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic BOOLEAN do_sar_reassembly (tL2C_CCB *p_ccb, BT_HDR *p_buf, UINT16 ctrl_word)
13895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
13905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    tL2C_FCRB   *p_fcrb = &p_ccb->fcrb;
13915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    UINT16      sar_type = ctrl_word & L2CAP_FCR_SEG_BITS;
13925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    BOOLEAN     packet_ok = TRUE;
13935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    UINT8       *p;
13945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
13955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Check if the SAR state is correct */
13965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if ((sar_type == L2CAP_FCR_UNSEG_SDU) || (sar_type == L2CAP_FCR_START_SDU))
13975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
13985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (p_fcrb->p_rx_sdu != NULL)
13995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
1400a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati            L2CAP_TRACE_WARNING ("SAR - got unexpected unsegmented or start SDU  Expected len: %u  Got so far: %u",
14015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                                  p_fcrb->rx_sdu_len, p_fcrb->p_rx_sdu->len);
14025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
14035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            packet_ok = FALSE;
14045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
14055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* Check the length of the packet */
14065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if ( (sar_type == L2CAP_FCR_START_SDU) && (p_buf->len < L2CAP_SDU_LEN_OVERHEAD) )
14075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
1408a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati            L2CAP_TRACE_WARNING ("SAR start packet too short: %u", p_buf->len);
14095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            packet_ok = FALSE;
14105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
14115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
14125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    else
14135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
14145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (p_fcrb->p_rx_sdu == NULL)
14155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
1416a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati            L2CAP_TRACE_WARNING ("SAR - got unexpected cont or end SDU");
14175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            packet_ok = FALSE;
14185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
14195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
14205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
14215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if ( (packet_ok) && (sar_type != L2CAP_FCR_UNSEG_SDU) )
14225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
14235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p = ((UINT8 *)(p_buf + 1)) + p_buf->offset;
14245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
14255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* For start SDU packet, extract the SDU length */
14265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (sar_type == L2CAP_FCR_START_SDU)
14275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
14285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* Get the SDU length */
14295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            STREAM_TO_UINT16 (p_fcrb->rx_sdu_len, p);
14305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_buf->offset += 2;
14315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_buf->len    -= 2;
14325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
14335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if (p_fcrb->rx_sdu_len > p_ccb->max_rx_mtu)
14345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
1435a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati                L2CAP_TRACE_WARNING ("SAR - SDU len: %u  larger than MTU: %u", p_fcrb->rx_sdu_len, p_fcrb->rx_sdu_len);
14365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                packet_ok = FALSE;
14375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
14385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            else if ((p_fcrb->p_rx_sdu = (BT_HDR *)GKI_getpoolbuf (p_ccb->ertm_info.user_rx_pool_id)) == NULL)
14395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
1440a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati                L2CAP_TRACE_ERROR ("SAR - no buffer for SDU start user_rx_pool_id:%d", p_ccb->ertm_info.user_rx_pool_id);
14415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                packet_ok = FALSE;
14425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
14435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            else
14445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
14455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                p_fcrb->p_rx_sdu->offset = 4; /* this is the minimal offset required by OBX to process incoming packets */
14465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                p_fcrb->p_rx_sdu->len    = 0;
14475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
14485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
14495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
14505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (packet_ok)
14515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
14525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if ((p_fcrb->p_rx_sdu->len + p_buf->len) > p_fcrb->rx_sdu_len)
14535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
1454a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati                L2CAP_TRACE_ERROR ("SAR - SDU len exceeded  Type: %u   Lengths: %u %u %u",
14555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                                    sar_type, p_fcrb->p_rx_sdu->len, p_buf->len, p_fcrb->rx_sdu_len);
14565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                packet_ok = FALSE;
14575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
14585738f83aeb59361a0a2eda2460113f6dc919427The 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) )
14595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
1460a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati                L2CAP_TRACE_WARNING ("SAR - SDU end rcvd but SDU incomplete: %u %u %u",
14615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                                      p_fcrb->p_rx_sdu->len, p_buf->len, p_fcrb->rx_sdu_len);
14625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                packet_ok = FALSE;
14635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
14645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            else
14655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
14665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                memcpy (((UINT8 *) (p_fcrb->p_rx_sdu + 1)) + p_fcrb->p_rx_sdu->offset + p_fcrb->p_rx_sdu->len, p, p_buf->len);
14675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
14685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                p_fcrb->p_rx_sdu->len += p_buf->len;
14695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
14705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                GKI_freebuf (p_buf);
14715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                p_buf = NULL;
14725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
14735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                if (sar_type == L2CAP_FCR_END_SDU)
14745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                {
14755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    p_buf            = p_fcrb->p_rx_sdu;
14765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    p_fcrb->p_rx_sdu = NULL;
14775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                }
14785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
14795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
14805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
14815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
14825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (packet_ok == FALSE)
14835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
14845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        GKI_freebuf (p_buf);
14855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
14865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    else if (p_buf != NULL)
14875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
14885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_NUM_FIXED_CHNLS > 0)
1489ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta        if (p_ccb->local_cid < L2CAP_BASE_APPL_CID &&
1490ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta            (p_ccb->local_cid >= L2CAP_FIRST_FIXED_CHNL && p_ccb->local_cid <= L2CAP_LAST_FIXED_CHNL))
1491ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta        {
1492ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta            if (l2cb.fixed_reg[p_ccb->local_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedData_Cb)
1493ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta                (*l2cb.fixed_reg[p_ccb->local_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedData_Cb)(p_ccb->p_lcb->remote_bd_addr, p_buf);
1494ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta        }
14955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        else
14965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
14975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            l2c_csm_execute (p_ccb, L2CEVT_L2CAP_DATA, p_buf);
14985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
14995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
15005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return (packet_ok);
15015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
15025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
15035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
15045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
15055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
15065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function         retransmit_i_frames
15075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
15085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description      This function retransmits i-frames awaiting acks.
15095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
15105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns          BOOLEAN - TRUE if retransmitted
15115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
15125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
15135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic BOOLEAN retransmit_i_frames (tL2C_CCB *p_ccb, UINT8 tx_seq)
15145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
15155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    BT_HDR      *p_buf, *p_buf2;
15165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    UINT8       *p;
15175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    UINT8       buf_seq;
15185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    UINT16      ctrl_word;
15195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
15205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if ( (p_ccb->fcrb.waiting_for_ack_q.p_first)
15215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project     &&  (p_ccb->peer_cfg.fcr.max_transmit != 0)
15225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project     &&  (p_ccb->fcrb.num_tries >= p_ccb->peer_cfg.fcr.max_transmit) )
15235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
1524a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati        L2CAP_TRACE_EVENT ("Max Tries Exceeded:  (last_acq: %d  CID: 0x%04x  num_tries: %u (max: %u) ack_q_count: %u",
15255738f83aeb59361a0a2eda2460113f6dc919427The 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,
15265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                p_ccb->fcrb.waiting_for_ack_q.count);
15275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
15285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        l2cu_disconnect_chnl (p_ccb);
15295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        return (FALSE);
15305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
15315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
15325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* tx_seq indicates whether to retransmit a specific sequence or all (if == L2C_FCR_RETX_ALL_PKTS) */
15335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (tx_seq != L2C_FCR_RETX_ALL_PKTS)
15345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
15355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* If sending only one, the sequence number tells us which one. Look for it.
15365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        */
15375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        for (p_buf = (BT_HDR *)p_ccb->fcrb.waiting_for_ack_q.p_first; p_buf; p_buf = (BT_HDR *)GKI_getnext (p_buf))
15385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
15395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* Get the old control word */
15405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p = ((UINT8 *) (p_buf+1)) + p_buf->offset + L2CAP_PKT_OVERHEAD;
15415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
15425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            STREAM_TO_UINT16 (ctrl_word, p);
15435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
15445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            buf_seq = (ctrl_word & L2CAP_FCR_TX_SEQ_BITS) >> L2CAP_FCR_TX_SEQ_BITS_SHIFT;
15455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1546a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati            L2CAP_TRACE_DEBUG ("retransmit_i_frames()   cur seq: %u  looking for: %u", buf_seq, tx_seq);
15475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
15485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if (tx_seq == buf_seq)
15495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                break;
15505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
15515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
15525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (!p_buf)
15535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
1554a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati            L2CAP_TRACE_ERROR ("retransmit_i_frames() UNKNOWN seq: %u  q_count: %u", tx_seq, p_ccb->fcrb.waiting_for_ack_q.count);
15555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            return (TRUE);
15565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
15575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
15585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    else
15595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
15605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* Retransmitting everything. Flush buffers we already put in the link xmit queue.
15615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        */
15625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_buf = (BT_HDR *)p_ccb->p_lcb->link_xmit_data_q.p_first;
15635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
15645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        while (p_buf != NULL)
15655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
15665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* Do not flush other CIDs or partial segments */
15675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if ( (p_buf->layer_specific == 0) && (p_buf->event == p_ccb->local_cid) )
15685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
15695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                p_buf2 = p_buf;
15705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                p_buf = (BT_HDR *)GKI_getnext (p_buf);
15715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
15725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                GKI_remove_from_queue (&p_ccb->p_lcb->link_xmit_data_q, p_buf2);
15735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                GKI_freebuf (p_buf2);
15745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
15755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            else
15765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                p_buf = (BT_HDR *)GKI_getnext (p_buf);
15775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
15785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
15795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* Also flush our retransmission queue */
15805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        while (p_ccb->fcrb.retrans_q.p_first)
15815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            GKI_freebuf (GKI_dequeue (&p_ccb->fcrb.retrans_q));
15825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
15835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_buf = (BT_HDR *)p_ccb->fcrb.waiting_for_ack_q.p_first;
15845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
15855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
15865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    while (p_buf != NULL)
15875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
15885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_buf2 = l2c_fcr_clone_buf (p_buf, p_buf->offset, p_buf->len, p_ccb->ertm_info.fcr_tx_pool_id);
15895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
15905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (p_buf2)
15915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
15925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_buf2->layer_specific = p_buf->layer_specific;
15935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
15945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            GKI_enqueue (&p_ccb->fcrb.retrans_q, p_buf2);
15955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
15965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
15975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if ( (tx_seq != L2C_FCR_RETX_ALL_PKTS) || (p_buf2 == NULL) )
15985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            break;
15995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        else
16005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_buf = (BT_HDR *)GKI_getnext (p_buf);
16015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
16025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
16035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, NULL);
16045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
16055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (p_ccb->fcrb.waiting_for_ack_q.count)
16065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
16075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_ccb->fcrb.num_tries++;
16085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        l2c_fcr_start_timer (p_ccb);
16095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
16105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
16115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return (TRUE);
16125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
16135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
16145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
16155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
16165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
16175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function         l2c_fcr_get_next_xmit_sdu_seg
16185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
16195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description      Get the next SDU segment to transmit.
16205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
16215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns          pointer to buffer with segment or NULL
16225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
16235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
16245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source ProjectBT_HDR *l2c_fcr_get_next_xmit_sdu_seg (tL2C_CCB *p_ccb, UINT16 max_packet_length)
16255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
16265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    BOOLEAN     first_seg    = FALSE,       /* The segment is the first part of data  */
16275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                mid_seg      = FALSE,       /* The segment is the middle part of data */
16285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                last_seg     = FALSE;       /* The segment is the last part of data   */
1629ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta    UINT16      sdu_len = 0;
16305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    BT_HDR      *p_buf, *p_xmit;
16315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    UINT8       *p;
16325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    UINT16      max_pdu = p_ccb->tx_mps /* Needed? - L2CAP_MAX_HEADER_FCS*/;
16335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
16345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* If there is anything in the retransmit queue, that goes first
16355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    */
16365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (p_ccb->fcrb.retrans_q.p_first)
16375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
16385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_buf = (BT_HDR *)GKI_dequeue (&p_ccb->fcrb.retrans_q);
16395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
16405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* Update Rx Seq and FCS if we acked some packets while this one was queued */
16415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        prepare_I_frame (p_ccb, p_buf, TRUE);
16425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
16435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_buf->event = p_ccb->local_cid;
16445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
16455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if L2CAP_CORRUPT_ERTM_PKTS == TRUE
16465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* Use sdu_len to hold the control word */
16475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p = ((UINT8 *) (p_buf+1)) + p_buf->offset + L2CAP_PKT_OVERHEAD;
16485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        STREAM_TO_UINT16 (sdu_len, p);
16495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
16505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* Get out if packet was dropped; just pretend it went out */
16515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (l2c_corrupt_the_fcr_packet (p_ccb, p_buf, FALSE, sdu_len))
16525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            return (NULL);
16535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif  /* L2CAP_CORRUPT_ERTM_PKTS */
16545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
16555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ERTM_STATS == TRUE)
16565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_ccb->fcrb.pkts_retransmitted++;
16575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_ccb->fcrb.ertm_pkt_counts[0]++;
16585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_ccb->fcrb.ertm_byte_counts[0] += (p_buf->len - 8);
16595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
16605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        return (p_buf);
16615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
16625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
16635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* For BD/EDR controller, max_packet_length is set to 0             */
16645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* For AMP controller, max_packet_length is set by available blocks */
16655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if ( (max_packet_length > L2CAP_MAX_HEADER_FCS)
16665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project      && (max_pdu + L2CAP_MAX_HEADER_FCS > max_packet_length) )
16675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
16685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        max_pdu = max_packet_length - L2CAP_MAX_HEADER_FCS;
16695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
16705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
16715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p_buf = (BT_HDR *)p_ccb->xmit_hold_q.p_first;
16725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
16735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* If there is more data than the MPS, it requires segmentation */
16745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (p_buf->len > max_pdu)
16755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
16765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* We are using the "event" field to tell is if we already started segmentation */
16775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (p_buf->event == 0)
16785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
16795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            first_seg = TRUE;
16805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            sdu_len   = p_buf->len;
16815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
16825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        else
16835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            mid_seg = TRUE;
16845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
16855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* Get a new buffer and copy the data that can be sent in a PDU */
16865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_xmit = l2c_fcr_clone_buf (p_buf, L2CAP_MIN_OFFSET + L2CAP_SDU_LEN_OFFSET,
16875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                                    max_pdu, p_ccb->ertm_info.fcr_tx_pool_id);
16885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
16895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (p_xmit != NULL)
16905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
16915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_buf->event  = p_ccb->local_cid;
16925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_xmit->event = p_ccb->local_cid;
16935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
16945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_buf->len    -= max_pdu;
16955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_buf->offset += max_pdu;
16965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
16975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* copy PBF setting */
16985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_xmit->layer_specific = p_buf->layer_specific;
16995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
17005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        else /* Should never happen if the application has configured buffers correctly */
17015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
1702a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati            L2CAP_TRACE_ERROR ("L2CAP - cannot get buffer, for segmentation, pool: %u", p_ccb->ertm_info.fcr_tx_pool_id);
17035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            return (NULL);
17045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
17055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
17065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    else    /* Use the original buffer if no segmentation, or the last segment */
17075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
17085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_xmit = (BT_HDR *)GKI_dequeue (&p_ccb->xmit_hold_q);
17095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
17105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (p_xmit->event != 0)
17115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            last_seg = TRUE;
17125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
17135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_xmit->event = p_ccb->local_cid;
17145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
17155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
17165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Step back to add the L2CAP headers */
17175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p_xmit->offset -= (L2CAP_PKT_OVERHEAD + L2CAP_FCR_OVERHEAD);
17185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p_xmit->len    += L2CAP_PKT_OVERHEAD + L2CAP_FCR_OVERHEAD;
17195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
17205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (first_seg)
17215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
17225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_xmit->offset -= L2CAP_SDU_LEN_OVERHEAD;
17235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_xmit->len    += L2CAP_SDU_LEN_OVERHEAD;
17245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
17255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
17265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Set the pointer to the beginning of the data */
17275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p = (UINT8 *)(p_xmit + 1) + p_xmit->offset;
17285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
17295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Now the L2CAP header */
17305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
17315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Note: if FCS has to be included then the length is recalculated later */
17325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    UINT16_TO_STREAM (p, p_xmit->len - L2CAP_PKT_OVERHEAD);
17335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
17345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    UINT16_TO_STREAM (p, p_ccb->remote_cid);
17355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
17365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (first_seg)
17375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
17385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* Skip control word and add SDU length */
17395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p += 2;
17405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        UINT16_TO_STREAM (p, sdu_len);
17415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
17425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* We will store the SAR type in layer-specific */
17435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* layer_specific is shared with flushable flag(bits 0-1), don't clear it */
17445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_xmit->layer_specific |= L2CAP_FCR_START_SDU;
17455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
17465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        first_seg = FALSE;
17475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
17485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    else if (mid_seg)
17495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_xmit->layer_specific |= L2CAP_FCR_CONT_SDU;
17505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    else if (last_seg)
17515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_xmit->layer_specific |= L2CAP_FCR_END_SDU;
17525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    else
17535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_xmit->layer_specific |= L2CAP_FCR_UNSEG_SDU;
17545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
17555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    prepare_I_frame (p_ccb, p_xmit, FALSE);
17565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
17575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE)
17585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
17595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        BT_HDR *p_wack = l2c_fcr_clone_buf (p_xmit, HCI_DATA_PREAMBLE_SIZE, p_xmit->len, p_ccb->ertm_info.fcr_tx_pool_id);
17605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
17615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (!p_wack)
17625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
1763a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati            L2CAP_TRACE_ERROR ("L2CAP - no buffer for xmit cloning, CID: 0x%04x  Pool: %u  Count: %u",
17645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                                p_ccb->local_cid, p_ccb->ertm_info.fcr_tx_pool_id,  GKI_poolfreecount(p_ccb->ertm_info.fcr_tx_pool_id));
17655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
17665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* We will not save the FCS in case we reconfigure and change options */
17675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if (p_ccb->bypass_fcs != L2CAP_BYPASS_FCS)
17685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                p_xmit->len -= L2CAP_FCS_LEN;
17695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
17705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* Pretend we sent it and it got lost */
17715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            GKI_enqueue (&p_ccb->fcrb.waiting_for_ack_q, p_xmit);
17725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            return (NULL);
17735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
17745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        else
17755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
17765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ERTM_STATS == TRUE)
17775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* set timestamp at the end of tx I-frame to get acking delay */
17785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p = ((UINT8 *) (p_wack+1)) + p_wack->offset + p_wack->len;
17795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            UINT32_TO_STREAM (p, GKI_get_os_tick_count());
17805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
17815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* We will not save the FCS in case we reconfigure and change options */
17825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if (p_ccb->bypass_fcs != L2CAP_BYPASS_FCS)
17835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                p_wack->len -= L2CAP_FCS_LEN;
17845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
17855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_wack->layer_specific = p_xmit->layer_specific;
17865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            GKI_enqueue (&p_ccb->fcrb.waiting_for_ack_q, p_wack);
17875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
17885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
17895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if L2CAP_CORRUPT_ERTM_PKTS == TRUE
17905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
17915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            UINT16 ctrl_word;
17925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p = ((UINT8 *) (p_xmit+1)) + p_xmit->offset + L2CAP_PKT_OVERHEAD;
17935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            STREAM_TO_UINT16 (ctrl_word, p);
17945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
17955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* Get out if packet was dropped; pretend it was sent */
17965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if (l2c_corrupt_the_fcr_packet (p_ccb, p_xmit, FALSE, ctrl_word))
17975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                return (NULL);
17985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
17995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
18005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ERTM_STATS == TRUE)
18015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_ccb->fcrb.ertm_pkt_counts[0]++;
18025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_ccb->fcrb.ertm_byte_counts[0] += (p_xmit->len - 8);
18035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
18045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
18055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
18065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
18075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return (p_xmit);
18085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
18095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
18105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
18115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
18125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Configuration negotiation functions
18135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
18145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** The following functions are used in negotiating channel modes during
18155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** configuration
18165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project********************************************************************************/
18175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
18185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
18195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
18205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function         l2c_fcr_chk_chan_modes
18215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
18225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description      Validates and adjusts if necessary, the FCR options
18235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  based on remote EXT features.
18245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
18255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  Note: This assumes peer EXT Features have been received.
18265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                      Basic mode is used if FCR Options have not been received
18275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
18285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns          UINT8 - nonzero if can continue, '0' if no compatible channels
18295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
18305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
18315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source ProjectUINT8 l2c_fcr_chk_chan_modes (tL2C_CCB *p_ccb)
18325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
18335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Remove nonbasic options that the peer does not support */
18345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (!(p_ccb->p_lcb->peer_ext_fea & L2CAP_EXTFEA_ENH_RETRANS))
18355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_ccb->ertm_info.allowed_modes &= ~L2CAP_FCR_CHAN_OPT_ERTM;
18365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
18375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (!(p_ccb->p_lcb->peer_ext_fea & L2CAP_EXTFEA_STREAM_MODE))
18385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_ccb->ertm_info.allowed_modes &= ~L2CAP_FCR_CHAN_OPT_STREAM;
18395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
18405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* At least one type needs to be set (Basic, ERTM, STM) to continue */
18415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (!p_ccb->ertm_info.allowed_modes)
18425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
1843a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati        L2CAP_TRACE_WARNING ("L2CAP - Peer does not support our desired channel types");
18445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
18455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
18465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return (p_ccb->ertm_info.allowed_modes);
18475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
18485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
18495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
18505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
18515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function         l2c_fcr_adj_our_req_options
18525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
18535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description      Validates and sets up the FCR options passed in from
18545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  L2CA_ConfigReq based on remote device's features.
18555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
18565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns          TRUE if no errors, Otherwise FALSE
18575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
18585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
18595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source ProjectBOOLEAN l2c_fcr_adj_our_req_options (tL2C_CCB *p_ccb, tL2CAP_CFG_INFO *p_cfg)
18605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
18615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    tL2CAP_FCR_OPTS *p_fcr = &p_cfg->fcr;
18625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
18635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (p_fcr->mode != p_ccb->ertm_info.preferred_mode)
18645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
1865a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati        L2CAP_TRACE_WARNING ("l2c_fcr_adj_our_req_options - preferred_mode (%d), does not match mode (%d)",
18665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                            p_ccb->ertm_info.preferred_mode, p_fcr->mode);
18675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
18685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* The preferred mode is passed in through tL2CAP_ERTM_INFO, so override this one */
18695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_fcr->mode = p_ccb->ertm_info.preferred_mode;
18705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
18715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
18725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* If upper layer did not request eRTM mode, BASIC must be used */
18735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (p_ccb->ertm_info.allowed_modes == L2CAP_FCR_CHAN_OPT_BASIC)
18745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
18755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (p_cfg->fcr_present && p_fcr->mode != L2CAP_FCR_BASIC_MODE)
18765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
1877a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati            L2CAP_TRACE_WARNING ("l2c_fcr_adj_our_req_options (mode %d): ERROR: No FCR options set using BASIC mode", p_fcr->mode);
18785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
18795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_fcr->mode = L2CAP_FCR_BASIC_MODE;
18805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
18815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
18825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Process the FCR options if initial channel bring-up (not a reconfig request)
18835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    ** Determine initial channel mode to try based on our options and remote's features
18845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    */
18855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (p_cfg->fcr_present && !(p_ccb->config_done & RECONFIG_FLAG))
18865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
18875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* We need to have at least one mode type common with the peer */
18885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (!l2c_fcr_chk_chan_modes(p_ccb))
18895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
18905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* Two channels have incompatible supported types */
18915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            l2cu_disconnect_chnl (p_ccb);
18925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            return (FALSE);
18935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
18945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
18955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* Basic is the only common channel mode between the two devices */
18965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        else if (p_ccb->ertm_info.allowed_modes == L2CAP_FCR_CHAN_OPT_BASIC)
18975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
18985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* We only want to try Basic, so bypass sending the FCR options entirely */
18995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_cfg->fcr_present = FALSE;
19005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_cfg->fcs_present = FALSE;             /* Illegal to use FCS option in basic mode */
19015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_cfg->ext_flow_spec_present = FALSE;   /* Illegal to use extended flow spec in basic mode */
19025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
19035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
19045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* We have at least one non-basic mode available
19055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project         * Override mode from available mode options based on preference, if needed
19065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project         */
19075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        else
19085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
19095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* If peer does not support STREAMING, try ERTM */
19105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if (p_fcr->mode == L2CAP_FCR_STREAM_MODE && !(p_ccb->ertm_info.allowed_modes & L2CAP_FCR_CHAN_OPT_STREAM))
19115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
1912a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati                L2CAP_TRACE_DEBUG ("L2C CFG: mode is STREAM, but peer does not support; Try ERTM");
19135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                p_fcr->mode = L2CAP_FCR_ERTM_MODE;
19145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
19155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
19165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* If peer does not support ERTM, try BASIC (will support this if made it here in the code) */
19175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if (p_fcr->mode == L2CAP_FCR_ERTM_MODE && !(p_ccb->ertm_info.allowed_modes & L2CAP_FCR_CHAN_OPT_ERTM))
19185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
1919a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati                L2CAP_TRACE_DEBUG ("L2C CFG: mode is ERTM, but peer does not support; Try BASIC");
19205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                p_fcr->mode = L2CAP_FCR_BASIC_MODE;
19215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
19225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
19235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
19245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (p_fcr->mode != L2CAP_FCR_BASIC_MODE)
19255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
19265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* MTU must be smaller than buffer size */
19275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if ( (p_cfg->mtu_present) && (p_cfg->mtu > p_ccb->max_rx_mtu) )
19285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
1929a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati                L2CAP_TRACE_WARNING ("L2CAP - MTU: %u  larger than buf size: %u", p_cfg->mtu, p_ccb->max_rx_mtu);
19305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                return (FALSE);
19315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
19325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
19335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* application want to use the default MPS */
19345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if (p_fcr->mps == L2CAP_DEFAULT_ERM_MPS)
19355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
19365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                p_fcr->mps = L2CAP_MPS_OVER_BR_EDR;
19375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
19385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* MPS must be less than MTU */
19395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            else if (p_fcr->mps > p_ccb->max_rx_mtu)
19405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
1941a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati                L2CAP_TRACE_WARNING ("L2CAP - MPS  %u  invalid  MTU: %u", p_fcr->mps, p_ccb->max_rx_mtu);
19425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                return (FALSE);
19435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
19445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
19455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* We always initially read into the HCI buffer pool, so make sure it fits */
19465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if (p_fcr->mps > (L2CAP_MTU_SIZE - L2CAP_MAX_HEADER_FCS))
19475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                p_fcr->mps = L2CAP_MTU_SIZE - L2CAP_MAX_HEADER_FCS;
19485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
19495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        else
19505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
19515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_cfg->fcs_present = FALSE;             /* Illegal to use FCS option in basic mode */
19525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_cfg->ext_flow_spec_present = FALSE;   /* Illegal to use extended flow spec in basic mode */
19535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
19545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
19555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_ccb->our_cfg.fcr = *p_fcr;
19565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
19575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    else    /* Not sure how to send a reconfiguration(??) should fcr be included? */
19585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
19595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_ccb->our_cfg.fcr_present = FALSE;
19605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
19615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
19625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return (TRUE);
19635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
19645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
19655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
19665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
19675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
19685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function         l2c_fcr_adj_monitor_retran_timeout
19695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
19705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description      Overrides monitor/retrans timer value based on controller
19715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
19725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns          None
19735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
19745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
19755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectvoid l2c_fcr_adj_monitor_retran_timeout (tL2C_CCB *p_ccb)
19765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
19775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* adjust our monitor/retran timeout */
19785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (p_ccb->out_cfg_fcr_present)
19795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
19805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /*
19815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        ** if we requestd ERTM or accepted ERTM
19825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        ** We may accept ERTM even if we didn't request ERTM, in case of requesting STREAM
19835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        */
19845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if ((p_ccb->our_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE)
19855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project          ||(p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE))
19865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
19875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* upper layer setting is ignored */
19885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_ccb->our_cfg.fcr.mon_tout    = L2CAP_MIN_MONITOR_TOUT;
19895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_ccb->our_cfg.fcr.rtrans_tout = L2CAP_MIN_RETRANS_TOUT;
19905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
19915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        else
19925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
19935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_ccb->our_cfg.fcr.mon_tout    = 0;
19945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_ccb->our_cfg.fcr.rtrans_tout = 0;
19955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
19965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1997a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati        L2CAP_TRACE_DEBUG ("l2c_fcr_adj_monitor_retran_timeout: mon_tout:%d, rtrans_tout:%d",
19985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                             p_ccb->our_cfg.fcr.mon_tout, p_ccb->our_cfg.fcr.rtrans_tout);
19995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
20005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
20015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
20025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
20035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function         l2c_fcr_adj_our_rsp_options
20045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
20055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description      Overrides any neccesary FCR options passed in from
20065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  L2CA_ConfigRsp based on our FCR options.
20075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  Only makes adjustments if channel is in ERTM mode.
20085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
20095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns          None
20105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
20115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
20125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectvoid l2c_fcr_adj_our_rsp_options (tL2C_CCB *p_ccb, tL2CAP_CFG_INFO *p_cfg)
20135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
20145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* adjust our monitor/retran timeout */
20155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    l2c_fcr_adj_monitor_retran_timeout(p_ccb);
20165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
20175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p_cfg->fcr_present = p_ccb->out_cfg_fcr_present;
20185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
20195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (p_cfg->fcr_present)
20205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
20215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project// btla-specific ++
20225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* Temporary - until a better algorithm is implemented */
20235738f83aeb59361a0a2eda2460113f6dc919427The 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. */
20245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* Note: peer is not guaranteed to obey our adjustment */
20255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (p_ccb->peer_cfg.fcr.tx_win_sz > p_ccb->our_cfg.fcr.tx_win_sz)
20265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
2027a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati            L2CAP_TRACE_DEBUG ("%s: adjusting requested tx_win_sz from %i to %i", __FUNCTION__, p_ccb->peer_cfg.fcr.tx_win_sz, p_ccb->our_cfg.fcr.tx_win_sz);
20285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_ccb->peer_cfg.fcr.tx_win_sz = p_ccb->our_cfg.fcr.tx_win_sz;
20295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
20305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project// btla-specific --
20315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
20325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_cfg->fcr.mode         = p_ccb->peer_cfg.fcr.mode;
20335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_cfg->fcr.tx_win_sz    = p_ccb->peer_cfg.fcr.tx_win_sz;
20345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_cfg->fcr.max_transmit = p_ccb->peer_cfg.fcr.max_transmit;
20355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_cfg->fcr.mps          = p_ccb->peer_cfg.fcr.mps;
20365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_cfg->fcr.rtrans_tout  = p_ccb->our_cfg.fcr.rtrans_tout;
20375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_cfg->fcr.mon_tout     = p_ccb->our_cfg.fcr.mon_tout;
20385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
20395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
20405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
20415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
20425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
20435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function         l2c_fcr_renegotiate_chan
20445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
20455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description      Called upon unsuccessful peer response to config request.
20465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  If the error is because of the channel mode, it will try
20475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  to resend using another supported optional channel.
20485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
20495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns          TRUE if resent configuration, False if channel matches or
20505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  cannot match.
20515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
20525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
20535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source ProjectBOOLEAN l2c_fcr_renegotiate_chan(tL2C_CCB *p_ccb, tL2CAP_CFG_INFO *p_cfg)
20545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
20555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    UINT8   peer_mode = p_ccb->our_cfg.fcr.mode;
20565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    BOOLEAN can_renegotiate;
20575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
20585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Skip if this is a reconfiguration from OPEN STATE or if FCR is not returned */
20595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (!p_cfg->fcr_present || (p_ccb->config_done & RECONFIG_FLAG))
20605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        return (FALSE);
20615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
20625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Only retry if there are more channel options to try */
20635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (p_cfg->result == L2CAP_CFG_UNACCEPTABLE_PARAMS)
20645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
20655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        peer_mode = (p_cfg->fcr_present) ? p_cfg->fcr.mode : L2CAP_FCR_BASIC_MODE;
20665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
20675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (p_ccb->our_cfg.fcr.mode != peer_mode)
20685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
20695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
20705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if ((--p_ccb->fcr_cfg_tries) == 0)
20715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
20725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                p_cfg->result = L2CAP_CFG_FAILED_NO_REASON;
2073a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati                L2CAP_TRACE_WARNING ("l2c_fcr_renegotiate_chan (Max retries exceeded)");
20745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
20755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
20765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            can_renegotiate = FALSE;
20775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
20785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* Try another supported mode if available based on our last attempted channel */
20795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            switch (p_ccb->our_cfg.fcr.mode)
20805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
20815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                /* Our Streaming mode request was unnacceptable; try ERTM or Basic */
20825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            case L2CAP_FCR_STREAM_MODE:
20835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                /* Peer wants ERTM and we support it */
20845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                if ( (peer_mode == L2CAP_FCR_ERTM_MODE) && (p_ccb->ertm_info.allowed_modes & L2CAP_FCR_CHAN_OPT_ERTM) )
20855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                {
2086a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati                    L2CAP_TRACE_DEBUG ("l2c_fcr_renegotiate_chan(Trying ERTM)");
20875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    p_ccb->our_cfg.fcr.mode = L2CAP_FCR_ERTM_MODE;
20885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    can_renegotiate = TRUE;
20895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                }
20905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                else    /* Falls through */
20915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
20925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            case L2CAP_FCR_ERTM_MODE:
20935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                {
20945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    /* We can try basic for any other peer mode if we support it */
20955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    if (p_ccb->ertm_info.allowed_modes & L2CAP_FCR_CHAN_OPT_BASIC)
20965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    {
2097a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati                        L2CAP_TRACE_DEBUG ("l2c_fcr_renegotiate_chan(Trying Basic)");
20985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                        can_renegotiate = TRUE;
20995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                        p_ccb->our_cfg.fcr.mode = L2CAP_FCR_BASIC_MODE;
21005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    }
21015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                }
21025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                break;
21035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
21045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            default:
21055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                /* All other scenarios cannot be renegotiated */
21065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                break;
21075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
21085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
21095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if (can_renegotiate)
21105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
21115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                p_ccb->our_cfg.fcr_present = TRUE;
21125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
21135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                if (p_ccb->our_cfg.fcr.mode == L2CAP_FCR_BASIC_MODE)
21145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                {
21155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    p_ccb->our_cfg.fcs_present = FALSE;
21165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    p_ccb->our_cfg.ext_flow_spec_present = FALSE;
21175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
21185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    /* Basic Mode uses ACL Data Pool, make sure the MTU fits */
21195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    if ( (p_cfg->mtu_present) && (p_cfg->mtu > L2CAP_MTU_SIZE) )
21205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    {
2121a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati                        L2CAP_TRACE_WARNING ("L2CAP - adjust MTU: %u too large", p_cfg->mtu);
21225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                        p_cfg->mtu = L2CAP_MTU_SIZE;
21235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    }
21245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                }
21255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
21265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                l2cu_process_our_cfg_req (p_ccb, &p_ccb->our_cfg);
21275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                l2cu_send_peer_config_req (p_ccb, &p_ccb->our_cfg);
21285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_L2CAP_CHNL, L2CAP_CHNL_CFG_TIMEOUT);
21295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                return (TRUE);
21305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
21315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
21325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
21335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
21345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Disconnect if the channels do not match */
21355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (p_ccb->our_cfg.fcr.mode != peer_mode)
21365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
2137a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati        L2CAP_TRACE_WARNING ("L2C CFG:  Channels incompatible (local %d, peer %d)",
21385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                              p_ccb->our_cfg.fcr.mode, peer_mode);
21395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        l2cu_disconnect_chnl (p_ccb);
21405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
21415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
21425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return (FALSE);
21435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
21445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
21455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
21465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
21475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
21485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function         l2c_fcr_process_peer_cfg_req
21495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
21505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description      This function is called to process the FCR options passed
21515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  in the peer's configuration request.
21525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
21535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns          UINT8 - L2CAP_PEER_CFG_OK, L2CAP_PEER_CFG_UNACCEPTABLE,
21545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                          or L2CAP_PEER_CFG_DISCONNECT.
21555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
21565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
21575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source ProjectUINT8 l2c_fcr_process_peer_cfg_req(tL2C_CCB *p_ccb, tL2CAP_CFG_INFO *p_cfg)
21585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
21595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    UINT16 max_retrans_size;
21605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    UINT8  fcr_ok = L2CAP_PEER_CFG_OK;
21615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
21625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p_ccb->p_lcb->w4_info_rsp = FALSE;      /* Handles T61x SonyEricsson Bug in Info Request */
21635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2164a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil 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",
21655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                        p_cfg->fcr_present, p_cfg->fcr.mode, p_ccb->our_cfg.fcr.mode, p_ccb->ertm_info.preferred_mode,
21665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                        p_ccb->ertm_info.allowed_modes);
21675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
21685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* If Peer wants basic, we are done (accept it or disconnect) */
21695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (p_cfg->fcr.mode == L2CAP_FCR_BASIC_MODE)
21705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
21715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* If we do not allow basic, disconnect */
21725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if ( !(p_ccb->ertm_info.allowed_modes & L2CAP_FCR_CHAN_OPT_BASIC) )
21735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            fcr_ok = L2CAP_PEER_CFG_DISCONNECT;
21745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
21755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
21765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Need to negotiate if our modes are not the same */
21775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    else if (p_cfg->fcr.mode != p_ccb->ertm_info.preferred_mode)
21785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
21795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* If peer wants a mode that we don't support then retry our mode (ex. rtx/flc), OR
21805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        ** If we want ERTM and they wanted streaming retry our mode.
21815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        ** Note: If we have already determined they support our mode previously
21825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        **       from their EXF mask.
21835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        */
21845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if ( (((1 << p_cfg->fcr.mode) & L2CAP_FCR_CHAN_OPT_ALL_MASK) == 0)
21855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            || (p_ccb->ertm_info.preferred_mode == L2CAP_FCR_ERTM_MODE) )
21865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
21875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_cfg->fcr.mode = p_ccb->our_cfg.fcr.mode;
21885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_cfg->fcr.tx_win_sz = p_ccb->our_cfg.fcr.tx_win_sz;
21895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_cfg->fcr.max_transmit = p_ccb->our_cfg.fcr.max_transmit;
21905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            fcr_ok = L2CAP_PEER_CFG_UNACCEPTABLE;
21915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
21925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
21935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* If we wanted basic, then try to renegotiate it */
21945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        else if (p_ccb->ertm_info.preferred_mode == L2CAP_FCR_BASIC_MODE)
21955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
21965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_cfg->fcr.mode = L2CAP_FCR_BASIC_MODE;
21975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_cfg->fcr.max_transmit = p_cfg->fcr.tx_win_sz = 0;
21985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_cfg->fcr.rtrans_tout = p_cfg->fcr.mon_tout = p_cfg->fcr.mps = 0;
21995738f83aeb59361a0a2eda2460113f6dc919427The 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;
22005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            fcr_ok = L2CAP_PEER_CFG_UNACCEPTABLE;
22015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
22025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
22035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* Only other valid case is if they want ERTM and we wanted STM which should be
22045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project           accepted if we support it; otherwise the channel should be disconnected */
22055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        else if ( (p_cfg->fcr.mode != L2CAP_FCR_ERTM_MODE)
22065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project              || !(p_ccb->ertm_info.allowed_modes & L2CAP_FCR_CHAN_OPT_ERTM) )
22075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
22085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            fcr_ok = L2CAP_PEER_CFG_DISCONNECT;
22095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
22105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
22115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
22125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Configuration for FCR channels so make any adjustments and fwd to upper layer */
22135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (fcr_ok == L2CAP_PEER_CFG_OK)
22145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
22155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* by default don't need to send params in the response */
22165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_ccb->out_cfg_fcr_present = FALSE;
22175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
22185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* Make any needed adjustments for the response to the peer */
22195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (p_cfg->fcr_present && p_cfg->fcr.mode != L2CAP_FCR_BASIC_MODE)
22205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
22215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* Peer desires to bypass FCS check, and streaming or ERTM mode */
22225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if (p_cfg->fcs_present)
22235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
22245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                p_ccb->peer_cfg.fcs = p_cfg->fcs;
22255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                p_ccb->peer_cfg_bits |= L2CAP_CH_CFG_MASK_FCS;
22265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                if( p_cfg->fcs == L2CAP_CFG_FCS_BYPASS)
22275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    p_ccb->bypass_fcs |= L2CAP_CFG_FCS_PEER;
22285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
22295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
22305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            max_retrans_size = GKI_get_pool_bufsize (p_ccb->ertm_info.fcr_tx_pool_id) - sizeof(BT_HDR)
22315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                                            - L2CAP_MIN_OFFSET - L2CAP_SDU_LEN_OFFSET - L2CAP_FCS_LEN;
22325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
22335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* Ensure the MPS is not bigger than the MTU */
22345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if ( (p_cfg->fcr.mps == 0) || (p_cfg->fcr.mps > p_ccb->peer_cfg.mtu) )
22355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
22365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                p_cfg->fcr.mps = p_ccb->peer_cfg.mtu;
22375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                p_ccb->out_cfg_fcr_present = TRUE;
22385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
22395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
22405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* Ensure the MPS is not bigger than our retransmission buffer */
22415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if (p_cfg->fcr.mps > max_retrans_size)
22425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
2243a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati                L2CAP_TRACE_DEBUG("CFG: Overriding MPS to %d (orig %d)", max_retrans_size, p_cfg->fcr.mps);
22445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
22455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                p_cfg->fcr.mps = max_retrans_size;
22465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                p_ccb->out_cfg_fcr_present = TRUE;
22475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
22485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
22498fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta            if (p_cfg->fcr.mode == L2CAP_FCR_ERTM_MODE || p_cfg->fcr.mode == L2CAP_FCR_STREAM_MODE)
22505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
22515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                /* Always respond with FCR ERTM parameters */
22525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                p_ccb->out_cfg_fcr_present = TRUE;
22535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
22545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
22555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
22565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* Everything ok, so save the peer's adjusted fcr options */
22575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_ccb->peer_cfg.fcr = p_cfg->fcr;
22585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
22595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (p_cfg->fcr_present)
22605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_ccb->peer_cfg_bits |= L2CAP_CH_CFG_MASK_FCR;
22615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
22625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    else if (fcr_ok == L2CAP_PEER_CFG_UNACCEPTABLE)
22635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
22645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* Allow peer only one retry for mode */
22655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (p_ccb->peer_cfg_already_rejected)
22665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            fcr_ok = L2CAP_PEER_CFG_DISCONNECT;
22675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        else
22685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_ccb->peer_cfg_already_rejected = TRUE;
22695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
22705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
22715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return (fcr_ok);
22725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
22735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
22745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
22755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if L2CAP_CORRUPT_ERTM_PKTS == TRUE
22765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
22775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**  Functions used for testing ERTM mode
22785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*/
22795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/* If FALSE, will also corrupt cid, length, control word, etc. */
22805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#ifndef L2CAP_CORR_FCS_ONLY
22815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#define L2CAP_CORR_FCS_ONLY TRUE
22825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
22835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
22845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#define L2C_DISP_FRAME_SIZE 16
22855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
22865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
22875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function         l2c_corrupt_the_fcr_packet
22885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
22895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description      This function is used for testing purposes only.
22905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  It systematically or randomly corrupts packets used with
22915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  ERTM channels.
22925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
22935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns          BOOLEAN   TRUE if packet was dropped,
22945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                            FALSE if fcs corrupted or no corruption
22955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
22965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
22975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic BOOLEAN l2c_corrupt_the_fcr_packet (tL2C_CCB *p_ccb, BT_HDR *p_buf,
22985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                                           BOOLEAN is_rx, UINT16 ctrl_word)
22995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
23005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    tL2C_FCR_TEST_CFG *p_cfg;
23015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    UINT32   tc;
23025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    UINT8   *p;
23035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    UINT32   xx;
23045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    char     buf[L2C_DISP_FRAME_SIZE];
23055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
23065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (!p_ccb || !p_ccb->fcrb.test_cb.cfg.in_use)
23075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        return FALSE;
23085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
23095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Prepare bad FCS */
23105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p = ((UINT8 *) (p_buf + 1)) + p_buf->offset;
23115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    tc = GKI_get_os_tick_count();
23125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    tc ^= p[p_buf->len - 1];
23135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    xx = tc % 47;
23145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
23155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p_cfg = &p_ccb->fcrb.test_cb.cfg;
23165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if 0
2317a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati    L2CAP_TRACE_DEBUG ("testcfg: type: %d, freq: %d (NRM-0, RDM-1), is_rx: %d, count: %d",
23185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_cfg->type, p_cfg->freq, p_cfg->is_rx, p_cfg->count);
23195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
23205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* If not time to corrupt get out */
23215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (p_cfg->freq == L2CAP_FCR_FREQ_RANDOM)
23225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
23235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (xx != 0)
23245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            return FALSE;
23255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
23265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    else    /* check test criteria before corrupting */
23275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
23285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if ( (p_cfg->count == 0)
23295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project          || (p_cfg->is_rx != is_rx)
23305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project          || ((UINT8)(ctrl_word & L2CAP_FCR_S_FRAME_BIT) != p_cfg->type) )
23315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
23325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            return FALSE;
23335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
23345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
23355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* Turn off if done */
23365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (--(p_cfg->count) == 0)
23375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
23385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_ccb->fcrb.test_cb.cfg.in_use = FALSE;
23395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
23405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
23415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
23425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if L2CAP_CORR_FCS_ONLY == TRUE
23435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Corrupt the FCS check */
23445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p[p_buf->len - 1] = p[p_buf->len - 2] = 0;
23455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#else
23465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* If made it this far packet needs to be corrupted */
23475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    xx = tc % p_buf->len;
23485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
23495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Make sure the value was changed */
23505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (p[xx + 1] == 0)
23515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p[xx + 1] = 0x5A;
23525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
23535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p[xx] = p[xx] ^ p[xx + 1];
23545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
23555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if 1   /* Enable if not wishing to corrupting frame type */
23565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
23575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        UINT8 *p_temp = ((UINT8 *) (p_buf + 1)) + p_buf->offset;
23585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_temp += L2CAP_PKT_OVERHEAD;
23595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if ((UINT16)((*p_temp) & 0x01) != (ctrl_word & 0x0001))
23605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
23615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            (*p_temp) |= (UINT8)(ctrl_word & 0x0001);
23625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
23635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
23645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
23655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
23665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
23675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (is_rx)
23685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
23695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (ctrl_word & L2CAP_FCR_S_FRAME_BIT)
23705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            BCM_STRCPY_S(buf, L2C_DISP_FRAME_SIZE, "Rx S-Frame");
23715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        else
23725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            BCM_STRCPY_S(buf, L2C_DISP_FRAME_SIZE, "Rx I-Frame");
23735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
23745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    else
23755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
23765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (ctrl_word & L2CAP_FCR_S_FRAME_BIT)
23775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            BCM_STRCPY_S(buf, L2C_DISP_FRAME_SIZE, "Tx S-Frame");
23785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        else
23795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            BCM_STRCPY_S(buf, L2C_DISP_FRAME_SIZE, "Tx I-Frame");
23805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
23815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
23825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Lastly, just drop packet if FCS is not being used or if Tx */
23835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (!is_rx || p_ccb->bypass_fcs == L2CAP_BYPASS_FCS)
23845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
2385a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati        L2CAP_TRACE_ERROR ("-=-=-=-=-=-=-=-   Dropping %s packet (0x%04x) tc: %u  Buf Len: %u  xx: %u  count: %d",
23865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                        buf, (UINT32)p_buf, tc, p_buf->len, xx, p_cfg->count);
23875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        GKI_freebuf(p_buf);
23885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        return TRUE;
23895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
23905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    else
23915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
2392a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati        L2CAP_TRACE_ERROR ("-=-=-=-=-=-=-=-   Corrupting %s packet (0x%04x) tc: %u  Buf Len: %u  xx: %u  count: %d",
23935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                        buf, (UINT32)p_buf, tc, p_buf->len, xx, p_cfg->count);
23945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
23955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
23965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return FALSE;
23975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
23985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
23995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
24005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
24015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
24025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function         L2CA_SetupErtmTest
24035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
24045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description      This function is used for testing purposes only.
24055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  It corrupts or drops one or more packets used with ERTM channels.
24065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
24075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Parameters
24085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  cid - channel ID  (0 uses RFCOMM PSM's CID)
24095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
24105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  type - type of test to run (L2CAP_FCR_TTYPE_CORR_IFRAMES
24115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                                              L2CAP_FCR_TTYPE_CORR_SFRAME
24125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                                              L2CAP_FCR_TTYPE_STOP_TEST
24135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                                              L2CAP_FCR_TTYPE_GET_CID - returns rfcomm cid only)
24145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
24155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  is_rx  - TRUE to corrupt Rx packet, FALSE for Tx packet)
24165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
24175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  freq - L2CAP_FCR_FREQ_RANDOM    (turns on random corruptions/drops)
24185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                         L2CAP_FCR_FREQ_NORMAL    (turns on test with "count" corruptions/drops)
24195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
24205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  count - number of packets in a row to drop or corrupt
24215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
24225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns          CID of channel running test
24235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
24245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
24255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source ProjectUINT16 L2CA_SetupErtmTest (UINT16 cid, UINT8 type, BOOLEAN is_rx, UINT8 freq, UINT16 count)
24265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
24275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    tL2C_CCB *p_ccb = NULL;
24285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    tL2C_CCB *p_temp_ccb;
24295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    tL2C_FCR_TEST_CB *p_test_cb;
24305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    UINT16 xx;
24315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
24325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* If '0' tests run on top of RFCOMM CID if active */
24335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (cid == 0)
24345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
24355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_temp_ccb = l2cb.ccb_pool;
24365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        for (xx = 0; xx < MAX_L2CAP_CHANNELS; xx++, p_temp_ccb++)
24375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
24385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* Fixed channels don't have p_rcb's */
24395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if (p_temp_ccb->in_use && p_temp_ccb->p_rcb && p_temp_ccb->p_rcb->psm == BT_PSM_RFCOMM)
24405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
24415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                p_ccb = p_temp_ccb;
24425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                cid = L2CAP_BASE_APPL_CID + xx;
24435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                break;
24445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
24455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
24465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
24475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    else
24485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_ccb = l2cu_find_ccb_by_cid (NULL, cid);
24495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
24505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (!p_ccb || type == L2CAP_FCR_TTYPE_GET_CID)
24515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
24525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (type == L2CAP_FCR_TTYPE_GET_CID)
24535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
2454a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati            L2CAP_TRACE_API ("L2CA_SetupErtmTest (GET_CID): cid = 0x%04x", cid);
24555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
24565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        return (cid);
24575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
24585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
24595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p_test_cb = &p_ccb->fcrb.test_cb;
24605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
24615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Turn off the current test */
24625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (type == L2CAP_FCR_TTYPE_STOP_TEST)
24635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
24645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (p_test_cb->cfg.in_use)
24655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
2466a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati            L2CAP_TRACE_ERROR ("L2CA_SetupErtmTest (OFF): cid 0x%04x", cid);
24675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
24685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_test_cb->cfg.in_use = FALSE;
24695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_test_cb->cfg.count = 0;
24705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
24715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
24725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Process the new request */
24735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    else if (!p_test_cb->cfg.in_use)
24745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
24755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* count must be positive unless random is used */
24765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (!count && freq != L2CAP_FCR_FREQ_RANDOM)
24775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
2478a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati            L2CAP_TRACE_ERROR ("L2CA_SetupErtmTest (FAIL): Count = 0, freq = %d", freq);
24795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            return (cid);
24805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
24815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2482a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati        L2CAP_TRACE_ERROR ("L2CA_SetupErtmTest (START): cid 0x%04x, type %d, is_rx %d, freq %d, count %d",
24835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                            cid, type, is_rx, freq, count);
24845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
24855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_test_cb->cfg.in_use = TRUE;
24865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_test_cb->cfg.freq = freq;
24875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_test_cb->cfg.type = type;
24885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_test_cb->cfg.is_rx = is_rx;
24895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_test_cb->cfg.count = count;
24905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
24915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    else /* Test already in progress so ignore */
24925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
2493a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati        L2CAP_TRACE_ERROR ("L2CA_SetupErtmTest (ignoring): cid 0x%04x, type %d, is_rx %d, freq %d, count %d",
24945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                            cid, type, is_rx, freq, count);
24955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
24965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
24975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return (cid);
24985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
24995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
25005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
25015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
25025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** The following routines are only used in conjunction with Conformance testing
25035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project********************************************************************************/
25045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
25055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
25065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
25075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function         L2CA_SendPolledSFrame
25085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
25095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description      This function is used for testing purposes only.
25105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  It Sends a Polled RR or RNR to the peer
25115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
25125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Parameters
25135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  cid - channel ID
25145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
25155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  sup_type - (L2CAP_FCR_SUP_RR or L2CAP_FCR_SUP_RNR)
25165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
25175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns          void
25185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
25195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
25205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectvoid L2CA_SendPolledSFrame (UINT16 cid, UINT16 sup_type)
25215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
25225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    tL2C_CCB *p_ccb = l2cu_find_ccb_by_cid (NULL, cid);
25235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
25245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (p_ccb && (sup_type == L2CAP_FCR_SUP_RR || sup_type == L2CAP_FCR_SUP_RNR))
25255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
25265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        l2c_fcr_send_S_frame (p_ccb, sup_type, L2CAP_FCR_P_BIT);
25275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
25285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    else
25295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
2530a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati        L2CAP_TRACE_ERROR ("L2CA_SendPolledSFrame(ERROR): sup_type %u, p_ccb 0x%07x",
25315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                            sup_type, (UINT32)p_ccb);
25325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
25335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
25345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
25355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
25365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
25375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function         l2c_bypass_sframe_packet
25385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
25395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description      This function is used for testing purposes only.
25405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  It returns TRUE if S-Frame should be bypassed.
25415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
25425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns          void
25435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
25445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
25455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic BOOLEAN l2c_bypass_sframe_packet (tL2C_CCB *p_ccb)
25465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
25475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (p_ccb && p_ccb->fcrb.test_cb.cfm.in_use)
25485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
25495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (p_ccb->fcrb.test_cb.cfm.skip_sframe_count > 0)
25505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
2551a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati            L2CAP_TRACE_ERROR ("l2c_bypass_sframe_packet (count %d)",
25525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                                p_ccb->fcrb.test_cb.cfm.skip_sframe_count);
25535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
25545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if (--p_ccb->fcrb.test_cb.cfm.skip_sframe_count == 0)
25555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                p_ccb->fcrb.test_cb.cfm.in_use = FALSE;
25565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
25575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* Bypass sending S-Frame */
25585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            return TRUE;
25595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
25605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        else
25615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_ccb->fcrb.test_cb.cfm.in_use = FALSE;
25625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
25635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
25645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return FALSE;
25655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
25665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
25675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
25685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
25695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function         L2CA_BypassSFrame
25705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
25715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description      This function is used for testing purposes only.
25725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  It skips sending 'count' S-Frames.
25735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
25745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Parameters
25755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  cid - channel ID
25765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
25775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  count - Number of S-Frames to skip sending
25785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
25795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns          void
25805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
25815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
25825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectvoid L2CA_BypassSFrame (UINT16 cid, UINT8 count)
25835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
25845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    tL2C_CCB *p_ccb = l2cu_find_ccb_by_cid (NULL, cid);
25855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    tL2C_FCR_CFM_TEST_CB *p_test_cb;
25865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
25875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (!p_ccb)
25885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
2589a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati        L2CAP_TRACE_WARNING ("L2CA_BypassSFrame(ERROR): no p_ccb (0x%07x)", (UINT32)p_ccb);
25905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        return;
25915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
25925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
25935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p_test_cb = &p_ccb->fcrb.test_cb.cfm;
25945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
25955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Initiate test if not active */
25965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (!p_test_cb->in_use)
25975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
25985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_test_cb->in_use = TRUE;
25995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_test_cb->skip_sframe_count = count;
26005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
26015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    else
26025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
2603a51c9d9d225e41fe36a0133f1c17fd981ea59c1dSharvil Nanavati        L2CAP_TRACE_WARNING ("L2CA_BypassSFrame(ERROR): already in use (ignoring...)");
26045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
26055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
26065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
26075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif  /* L2CAP_CORRUPT_ERTM_PKTS == TRUE */
26085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
26095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ERTM_STATS == TRUE)
26105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
26115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
26125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function         l2c_fcr_collect_ack_delay
26135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
26145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description      collect throughput, delay, queue size of waiting ack
26155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
26165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Parameters
26175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  tL2C_CCB
26185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
26195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns          void
26205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
26215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
26225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic void l2c_fcr_collect_ack_delay (tL2C_CCB *p_ccb, UINT8 num_bufs_acked)
26235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
26245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    UINT32  index;
26255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    BT_HDR *p_buf;
26265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    UINT8  *p;
26275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    UINT32  timestamp, delay;
26285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    UINT8   xx;
26295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    UINT8   str[120];
26305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
26315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    index = p_ccb->fcrb.ack_delay_avg_index;
26325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
26335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* update sum, max and min of waiting for ack queue size */
26345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p_ccb->fcrb.ack_q_count_avg[index] += p_ccb->fcrb.waiting_for_ack_q.count;
26355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
26365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if ( p_ccb->fcrb.waiting_for_ack_q.count > p_ccb->fcrb.ack_q_count_max[index] )
26375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_ccb->fcrb.ack_q_count_max[index] = p_ccb->fcrb.waiting_for_ack_q.count;
26385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
26395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if ( p_ccb->fcrb.waiting_for_ack_q.count < p_ccb->fcrb.ack_q_count_min[index] )
26405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_ccb->fcrb.ack_q_count_min[index] = p_ccb->fcrb.waiting_for_ack_q.count;
26415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
26425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* update sum, max and min of round trip delay of acking */
26435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p_buf = (BT_HDR *)(p_ccb->fcrb.waiting_for_ack_q.p_first);
26445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    for (xx = 0; (xx < num_bufs_acked)&&(p_buf); xx++)
26455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
26465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* adding up length of acked I-frames to get throughput */
26475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_ccb->fcrb.throughput[index] += p_buf->len - 8;
26485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
26495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if ( xx == num_bufs_acked - 1 )
26505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
26515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* get timestamp from tx I-frame that receiver is acking */
26525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p = ((UINT8 *) (p_buf+1)) + p_buf->offset + p_buf->len;
26535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if (p_ccb->bypass_fcs != L2CAP_BYPASS_FCS)
26545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
26555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                p += L2CAP_FCS_LEN;
26565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
26575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
26585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            STREAM_TO_UINT32 (timestamp, p);
26595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            delay = GKI_get_os_tick_count() - timestamp;
26605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
26615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_ccb->fcrb.ack_delay_avg[index] += delay;
26625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if ( delay > p_ccb->fcrb.ack_delay_max[index] )
26635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                p_ccb->fcrb.ack_delay_max[index] = delay;
26645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if ( delay < p_ccb->fcrb.ack_delay_min[index] )
26655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                p_ccb->fcrb.ack_delay_min[index] = delay;
26665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
26675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
26685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_buf = GKI_getnext(p_buf);
26695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
26705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
26715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p_ccb->fcrb.ack_delay_avg_count++;
26725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
26735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* calculate average and initialize next avg, min and max */
26745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (p_ccb->fcrb.ack_delay_avg_count > L2CAP_ERTM_STATS_AVG_NUM_SAMPLES)
26755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
26765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_ccb->fcrb.ack_delay_avg_count = 0;
26775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
26785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_ccb->fcrb.ack_q_count_avg[index] /= L2CAP_ERTM_STATS_AVG_NUM_SAMPLES;
26795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_ccb->fcrb.ack_delay_avg[index] /= L2CAP_ERTM_STATS_AVG_NUM_SAMPLES;
26805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
26815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* calculate throughput */
26825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        timestamp = GKI_get_os_tick_count();
26835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (timestamp - p_ccb->fcrb.throughput_start > 0 )
26845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_ccb->fcrb.throughput[index] /= (timestamp - p_ccb->fcrb.throughput_start);
26855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
26865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_ccb->fcrb.throughput_start = timestamp;
26875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
26885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        sprintf(str, "[%02u] throughput: %5u, ack_delay avg:%3u, min:%3u, max:%3u, ack_q_count avg:%3u, min:%3u, max:%3u",
26895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                index, p_ccb->fcrb.throughput[index],
26905738f83aeb59361a0a2eda2460113f6dc919427The 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],
26915738f83aeb59361a0a2eda2460113f6dc919427The 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] );
26925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
26930212487880be33e255d49f6e38dbb035d1f77750Sharvil Nanavati        BT_TRACE(TRACE_CTRL_GENERAL | TRACE_LAYER_GKI | TRACE_ORG_GKI , TRACE_TYPE_GENERIC, "%s", str);
26945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
26955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        index = (index + 1) % L2CAP_ERTM_STATS_NUM_AVG;
26965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_ccb->fcrb.ack_delay_avg_index = index;
26975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
26985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_ccb->fcrb.ack_q_count_max[index] = 0;
26995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_ccb->fcrb.ack_q_count_min[index] = 0xFFFFFFFF;
27005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_ccb->fcrb.ack_q_count_avg[index] = 0;
27015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
27025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
27035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_ccb->fcrb.ack_delay_max[index] = 0;
27045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_ccb->fcrb.ack_delay_min[index] = 0xFFFFFFFF;
27055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_ccb->fcrb.ack_delay_avg[index] = 0;
27065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
27075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_ccb->fcrb.throughput[index] = 0;
27085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
27095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
27105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
27115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
27125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
27135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2714