16ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach/****************************************************************************** 26ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach * 36ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach * Copyright (C) 1999-2012 Broadcom Corporation 46ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach * 56ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach * Licensed under the Apache License, Version 2.0 (the "License"); 66ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach * you may not use this file except in compliance with the License. 76ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach * You may obtain a copy of the License at: 86ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach * 96ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach * http://www.apache.org/licenses/LICENSE-2.0 106ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach * 116ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach * Unless required by applicable law or agreed to in writing, software 126ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach * distributed under the License is distributed on an "AS IS" BASIS, 136ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 146ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach * See the License for the specific language governing permissions and 156ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach * limitations under the License. 166ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach * 176ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach ******************************************************************************/ 186ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach 196ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach/****************************************************************************** 206ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach * 216ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach * This file contains the main L2CAP entry points 226ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach * 236ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach ******************************************************************************/ 24e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 25e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#include "bt_target.h" 26e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#include <stdlib.h> 27e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#include <string.h> 28e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#include <stdio.h> 29e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 30e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#include "gki.h" 31e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#include "hcimsgs.h" 32e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#include "l2cdefs.h" 33e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#include "l2c_int.h" 34e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#include "l2c_api.h" 35e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#include "btu.h" 36e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#include "btm_int.h" 37e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 38e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/********************************************************************************/ 39e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/* L O C A L F U N C T I O N P R O T O T Y P E S */ 40e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/********************************************************************************/ 41e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbachstatic void process_l2cap_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len); 42e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 43e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/********************************************************************************/ 44e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/* G L O B A L L 2 C A P D A T A */ 45e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/********************************************************************************/ 46e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#if L2C_DYNAMIC_MEMORY == FALSE 47e448862a47c08eb23185aaed574b39264f5005fcAndre EisenbachtL2C_CB l2cb; 48e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#endif 49e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 50e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/* Temporary - until l2cap implements group management */ 51e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#if (TCS_BCST_SETUP_INCLUDED == TRUE && TCS_INCLUDED == TRUE) 52e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbachextern void tcs_proc_bcst_msg( BD_ADDR addr, BT_HDR *p_msg ) ; 53e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 54e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/******************************************************************************* 55e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 56e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function l2c_bcst_msg 57e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 586ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach** Description 59e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 60e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Returns void 61e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 62e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/ 63e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbachvoid l2c_bcst_msg( BT_HDR *p_buf, UINT16 psm ) 64e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{ 65e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach UINT8 *p; 66e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 67e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* Ensure we have enough space in the buffer for the L2CAP and HCI headers */ 68e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (p_buf->offset < L2CAP_BCST_MIN_OFFSET) 69e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 70e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach L2CAP_TRACE_ERROR1 ("L2CAP - cannot send buffer, offset: %d", p_buf->offset); 71e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach GKI_freebuf (p_buf); 72e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach return; 73e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 74e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 75e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* Step back some bytes to add the headers */ 76e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_buf->offset -= (HCI_DATA_PREAMBLE_SIZE + L2CAP_PKT_OVERHEAD + L2CAP_BCST_OVERHEAD); 77e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_buf->len += L2CAP_PKT_OVERHEAD + L2CAP_BCST_OVERHEAD; 78e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 79e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* Set the pointer to the beginning of the data */ 80e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p = (UINT8 *)(p_buf + 1) + p_buf->offset; 81e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 82e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* First, the HCI transport header */ 83e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach UINT16_TO_STREAM (p, 0x0050 | (L2CAP_PKT_START << 12) | (2 << 14)); 84e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 85e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* The HCI transport will segment the buffers. */ 86e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (p_buf->len > btu_cb.hcit_acl_data_size) 87e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 88e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach UINT16_TO_STREAM (p, btu_cb.hcit_acl_data_size); 89e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 90e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach else 91e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 92e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach UINT16_TO_STREAM (p, p_buf->len); 93e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 94e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 95e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* Now the L2CAP header */ 96e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach UINT16_TO_STREAM (p, p_buf->len - L2CAP_PKT_OVERHEAD); 97e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach UINT16_TO_STREAM (p, L2CAP_CONNECTIONLESS_CID); 98e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach UINT16_TO_STREAM (p, psm); 99e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 100e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_buf->len += HCI_DATA_PREAMBLE_SIZE; 101e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 102e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (p_buf->len <= btu_cb.hcit_acl_pkt_size) 103e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 104e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach HCI_ACL_DATA_TO_LOWER (p_buf); 105e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 106e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach} 107e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#endif 108e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 109e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/******************************************************************************* 110e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 111e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function l2c_rcv_acl_data 112e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 113e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Description This function is called from the HCI Interface when an ACL 114e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** data packet is received. 115e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 116e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Returns void 117e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 118e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/ 119e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbachvoid l2c_rcv_acl_data (BT_HDR *p_msg) 120e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{ 121e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach UINT8 *p = (UINT8 *)(p_msg + 1) + p_msg->offset; 122e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach UINT16 handle, hci_len; 123e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach UINT8 pkt_type; 124e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach tL2C_LCB *p_lcb; 125e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach tL2C_CCB *p_ccb = NULL; 126e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach UINT16 l2cap_len, rcv_cid, psm; 127e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 128e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* Extract the handle */ 129e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT16 (handle, p); 130e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach pkt_type = HCID_GET_EVENT (handle); 131e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach handle = HCID_GET_HANDLE (handle); 132e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 133e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* Since the HCI Transport is putting segmented packets back together, we */ 134e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* should never get a valid packet with the type set to "continuation" */ 135e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (pkt_type != L2CAP_PKT_CONTINUE) 136e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 137e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* Find the LCB based on the handle */ 138e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if ((p_lcb = l2cu_find_lcb_by_handle (handle)) == NULL) 139e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 140e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach UINT8 cmd_code; 141e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 142e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* There is a slight possibility (specifically with USB) that we get an */ 143e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* L2CAP connection request before we get the HCI connection complete. */ 144e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* So for these types of messages, hold them for up to 2 seconds. */ 145e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT16 (hci_len, p); 146e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT16 (l2cap_len, p); 147e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT16 (rcv_cid, p); 148e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT8 (cmd_code, p); 149e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 150e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if ((p_msg->layer_specific == 0) && (rcv_cid == L2CAP_SIGNALLING_CID) 151e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach && (cmd_code == L2CAP_CMD_INFO_REQ || cmd_code == L2CAP_CMD_CONN_REQ)) 152e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 153e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach L2CAP_TRACE_WARNING5 ("L2CAP - holding ACL for unknown handle:%d ls:%d cid:%d opcode:%d cur count:%d", 154e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach handle, p_msg->layer_specific, rcv_cid, cmd_code, 155e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach l2cb.rcv_hold_q.count); 156e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_msg->layer_specific = 2; 157e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach GKI_enqueue (&l2cb.rcv_hold_q, p_msg); 158e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 159e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (l2cb.rcv_hold_q.count == 1) 160e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach btu_start_timer (&l2cb.rcv_hold_tle, BTU_TTYPE_L2CAP_HOLD, BT_1SEC_TIMEOUT); 161e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 162e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach return; 163e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 164e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach else 165e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 166e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach L2CAP_TRACE_ERROR5 ("L2CAP - rcvd ACL for unknown handle:%d ls:%d cid:%d opcode:%d cur count:%d", 167e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach handle, p_msg->layer_specific, rcv_cid, cmd_code, l2cb.rcv_hold_q.count); 168e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 169e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach GKI_freebuf (p_msg); 170e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach return; 171e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 172e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 173e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach else 174e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 175e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach L2CAP_TRACE_WARNING1 ("L2CAP - expected pkt start or complete, got: %d", pkt_type); 176e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach GKI_freebuf (p_msg); 177e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach return; 178e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 179e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 180e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* Extract the length and update the buffer header */ 181e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT16 (hci_len, p); 182e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_msg->offset += 4; 183e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 184e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#if (L2CAP_HOST_FLOW_CTRL == TRUE) 185e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* Send ack if we hit the threshold */ 186e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (++p_lcb->link_pkts_unacked >= p_lcb->link_ack_thresh) 187e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach btu_hcif_send_host_rdy_for_data(); 188e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#endif 189e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 190e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* Extract the length and CID */ 191e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT16 (l2cap_len, p); 192e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT16 (rcv_cid, p); 193e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 194e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* Find the CCB for this CID */ 195e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (rcv_cid >= L2CAP_BASE_APPL_CID) 196e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 197e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if ((p_ccb = l2cu_find_ccb_by_cid (p_lcb, rcv_cid)) == NULL) 198e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 199e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach L2CAP_TRACE_WARNING1 ("L2CAP - unknown CID: 0x%04x", rcv_cid); 200e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach GKI_freebuf (p_msg); 201e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach return; 202e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 203e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 204e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 205e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (hci_len >= L2CAP_PKT_OVERHEAD) /* Must receive at least the L2CAP length and CID.*/ 206e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 207e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_msg->len = hci_len - L2CAP_PKT_OVERHEAD; 208e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_msg->offset += L2CAP_PKT_OVERHEAD; 209e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 210e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach else 211e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 212e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach L2CAP_TRACE_WARNING0 ("L2CAP - got incorrect hci header" ); 213e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach GKI_freebuf (p_msg); 214e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach return; 215e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 216e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 217e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (l2cap_len != p_msg->len) 218e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 219e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach L2CAP_TRACE_WARNING2 ("L2CAP - bad length in pkt. Exp: %d Act: %d", 220e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach l2cap_len, p_msg->len); 221e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 222e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach GKI_freebuf (p_msg); 223e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach return; 224e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 225e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 226e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* Send the data through the channel state machine */ 227e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (rcv_cid == L2CAP_SIGNALLING_CID) 228e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 229e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach process_l2cap_cmd (p_lcb, p, l2cap_len); 230e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach GKI_freebuf (p_msg); 231e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 232e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach else if (rcv_cid == L2CAP_CONNECTIONLESS_CID) 233e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 234e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* process_connectionless_data (p_lcb); */ 235e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT16 (psm, p); 236e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach L2CAP_TRACE_DEBUG1( "GOT CONNECTIONLESS DATA PSM:%d", psm ) ; 237e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#if (TCS_BCST_SETUP_INCLUDED == TRUE && TCS_INCLUDED == TRUE) 238e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (psm == TCS_PSM_INTERCOM || psm == TCS_PSM_CORDLESS) 239e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 240e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_msg->offset += L2CAP_BCST_OVERHEAD; 241e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_msg->len -= L2CAP_BCST_OVERHEAD; 242e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach tcs_proc_bcst_msg( p_lcb->remote_bd_addr, p_msg ) ; 243e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach GKI_freebuf (p_msg); 244e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 245e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach else 246e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#endif 247e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 248e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#if (L2CAP_UCD_INCLUDED == TRUE) 249e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* if it is not broadcast, check UCD registration */ 250e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if ( l2c_ucd_check_rx_pkts( p_lcb, p_msg ) ) 251e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 252e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* nothing to do */ 253e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 254e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach else 255e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#endif 256e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach GKI_freebuf (p_msg); 257e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 258e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#if (BLE_INCLUDED == TRUE) 259e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach else if (rcv_cid == L2CAP_BLE_SIGNALLING_CID) 260e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 261e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach l2cble_process_sig_cmd (p_lcb, p, l2cap_len); 262e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach GKI_freebuf (p_msg); 263e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 264e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#endif 265e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#if (L2CAP_NUM_FIXED_CHNLS > 0) 2666ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach else if ((rcv_cid >= L2CAP_FIRST_FIXED_CHNL) && (rcv_cid <= L2CAP_LAST_FIXED_CHNL) && 267e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach (l2cb.fixed_reg[rcv_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedData_Cb != NULL) ) 268e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 269e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* If no CCB for this channel, allocate one */ 270e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (l2cu_initialize_fixed_ccb (p_lcb, rcv_cid, &l2cb.fixed_reg[rcv_cid - L2CAP_FIRST_FIXED_CHNL].fixed_chnl_opts)) 271e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 272e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_ccb = p_lcb->p_fixed_ccbs[rcv_cid - L2CAP_FIRST_FIXED_CHNL]; 273e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 274e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE) 275e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach l2c_fcr_proc_pdu (p_ccb, p_msg); 276e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach else 2776ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach (*l2cb.fixed_reg[rcv_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedData_Cb)(p_lcb->remote_bd_addr, p_msg); 278e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 279e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach else 280e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach GKI_freebuf (p_msg); 281e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 282e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#endif 283e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 284e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach else 285e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 286e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (p_ccb == NULL) 287e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach GKI_freebuf (p_msg); 288e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach else 289e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 290e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* Basic mode packets go straight to the state machine */ 291e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_BASIC_MODE) 292e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach l2c_csm_execute (p_ccb, L2CEVT_L2CAP_DATA, p_msg); 293e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach else 294e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 295e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* eRTM or streaming mode, so we need to validate states first */ 296e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if ((p_ccb->chnl_state == CST_OPEN) || (p_ccb->chnl_state == CST_CONFIG)) 297e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach l2c_fcr_proc_pdu (p_ccb, p_msg); 298e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach else 299e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach GKI_freebuf (p_msg); 300e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 301e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 302e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 303e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach} 304e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 305e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/******************************************************************************* 306e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 307e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function process_l2cap_cmd 308e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 309e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Description This function is called when a packet is received on the 310e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** L2CAP signalling CID 311e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 312e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Returns void 313e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 314e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/ 315e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbachstatic void process_l2cap_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len) 316e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{ 317e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach UINT8 *p_pkt_end, *p_next_cmd, *p_cfg_end, *p_cfg_start; 318e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach UINT8 cmd_code, cfg_code, cfg_len, id; 319e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach tL2C_CONN_INFO con_info; 320e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach tL2CAP_CFG_INFO cfg_info; 321e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach UINT16 rej_reason, rej_mtu, lcid, rcid, info_type; 322e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach tL2C_CCB *p_ccb; 323e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach tL2C_RCB *p_rcb; 324e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach BOOLEAN cfg_rej; 325e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach UINT16 cfg_rej_len, cmd_len; 326e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach UINT16 result; 327e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach tL2C_CONN_INFO ci; 328e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 329e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE) 330e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* if l2cap command received in CID 1 on top of an LE link, ignore this command */ 331e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (p_lcb->is_ble_link) 332e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach return; 333e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#endif 334e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_next_cmd = p; 335e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_pkt_end = p + pkt_len; 336e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 337e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach memset (&cfg_info, 0, sizeof(cfg_info)); 338e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 339e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* An L2CAP packet may contain multiple commands */ 340e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach while (TRUE) 341e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 342e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* Smallest command is 4 bytes */ 343e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if ((p = p_next_cmd) > (p_pkt_end - 4)) 344e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach break; 345e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 346e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT8 (cmd_code, p); 347e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT8 (id, p); 348e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT16 (cmd_len, p); 349e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 350e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* Check command length does not exceed packet length */ 351e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if ((p_next_cmd = p + cmd_len) > p_pkt_end) 352e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 353e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach L2CAP_TRACE_WARNING3 ("Command len bad pkt_len: %d cmd_len: %d code: %d", 354e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach pkt_len, cmd_len, cmd_code); 355e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach break; 356e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 357e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 358e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach switch (cmd_code) 359e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 360e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach case L2CAP_CMD_REJECT: 361e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT16 (rej_reason, p); 362e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (rej_reason == L2CAP_CMD_REJ_MTU_EXCEEDED) 363e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 364e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT16 (rej_mtu, p); 365e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* What to do with the MTU reject ? We have negotiated an MTU. For now */ 366e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* we will ignore it and let a higher protocol timeout take care of it */ 367e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 368e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach L2CAP_TRACE_WARNING2 ("L2CAP - MTU rej Handle: %d MTU: %d", p_lcb->handle, rej_mtu); 369e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 370e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (rej_reason == L2CAP_CMD_REJ_INVALID_CID) 371e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 372e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT16 (rcid, p); 373e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT16 (lcid, p); 374e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 375e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach L2CAP_TRACE_WARNING2 ("L2CAP - rej with CID invalid, LCID: 0x%04x RCID: 0x%04x", lcid, rcid); 376e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 377e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* Remote CID invalid. Treat as a disconnect */ 378e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (((p_ccb = l2cu_find_ccb_by_cid (p_lcb, lcid)) != NULL) 379e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach && (p_ccb->remote_cid == rcid)) 380e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 381e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* Fake link disconnect - no reply is generated */ 382e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach l2c_csm_execute (p_ccb, L2CEVT_LP_DISCONNECT_IND, NULL); 383e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 384e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 385e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 386e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* SonyEricsson Info request Bug workaround (Continue connection) */ 387e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach else if (rej_reason == L2CAP_CMD_REJ_NOT_UNDERSTOOD && p_lcb->w4_info_rsp) 388e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 389e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach btu_stop_timer (&p_lcb->info_timer_entry); 390e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 391e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_lcb->w4_info_rsp = FALSE; 392e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach ci.status = HCI_SUCCESS; 393e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach memcpy (ci.bd_addr, p_lcb->remote_bd_addr, sizeof(BD_ADDR)); 394e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 395e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* For all channels, send the event through their FSMs */ 396e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_ccb->p_next_ccb) 397e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 398e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach l2c_csm_execute (p_ccb, L2CEVT_L2CAP_INFO_RSP, &ci); 399e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 400e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 401e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach break; 402e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 403e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach case L2CAP_CMD_CONN_REQ: 404e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT16 (con_info.psm, p); 405e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT16 (rcid, p); 406e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if ((p_rcb = l2cu_find_rcb_by_psm (con_info.psm)) == NULL) 407e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 408e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach L2CAP_TRACE_WARNING1 ("L2CAP - rcvd conn req for unknown PSM: %d", con_info.psm); 409e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach l2cu_reject_connection (p_lcb, rcid, id, L2CAP_CONN_NO_PSM); 410e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach break; 411e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 412e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach else 413e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 414e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (!p_rcb->api.pL2CA_ConnectInd_Cb) 415e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 416e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach L2CAP_TRACE_WARNING1 ("L2CAP - rcvd conn req for outgoing-only connection PSM: %d", con_info.psm); 417e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach l2cu_reject_connection (p_lcb, rcid, id, L2CAP_CONN_NO_PSM); 418e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach break; 419e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 420e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 421e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if ((p_ccb = l2cu_allocate_ccb (p_lcb, 0)) == NULL) 422e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 423e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach L2CAP_TRACE_ERROR0 ("L2CAP - unable to allocate CCB"); 424e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach l2cu_reject_connection (p_lcb, rcid, id, L2CAP_CONN_NO_RESOURCES); 425e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach break; 426e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 427e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_ccb->remote_id = id; 428e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_ccb->p_rcb = p_rcb; 429e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_ccb->remote_cid = rcid; 430e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 431e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach l2c_csm_execute(p_ccb, L2CEVT_L2CAP_CONNECT_REQ, &con_info); 432e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach break; 433e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 434e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach case L2CAP_CMD_CONN_RSP: 435e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT16 (con_info.remote_cid, p); 436e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT16 (lcid, p); 437e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT16 (con_info.l2cap_result, p); 438e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT16 (con_info.l2cap_status, p); 439e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 440e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if ((p_ccb = l2cu_find_ccb_by_cid (p_lcb, lcid)) == NULL) 441e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 442e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach L2CAP_TRACE_WARNING2 ("L2CAP - no CCB for conn rsp, LCID: %d RCID: %d", 443e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach lcid, con_info.remote_cid); 444e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach break; 445e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 446e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (p_ccb->local_id != id) 447e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 448e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach L2CAP_TRACE_WARNING2 ("L2CAP - con rsp - bad ID. Exp: %d Got: %d", 449e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_ccb->local_id, id); 450e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach break; 451e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 452e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 453e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (con_info.l2cap_result == L2CAP_CONN_OK) 454e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach l2c_csm_execute(p_ccb, L2CEVT_L2CAP_CONNECT_RSP, &con_info); 455e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach else if (con_info.l2cap_result == L2CAP_CONN_PENDING) 456e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach l2c_csm_execute(p_ccb, L2CEVT_L2CAP_CONNECT_RSP_PND, &con_info); 457e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach else 458e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach l2c_csm_execute(p_ccb, L2CEVT_L2CAP_CONNECT_RSP_NEG, &con_info); 459e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 460e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach break; 461e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 462e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach case L2CAP_CMD_CONFIG_REQ: 463e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_cfg_end = p + cmd_len; 464e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach cfg_rej = FALSE; 465e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach cfg_rej_len = 0; 466e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 467e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT16 (lcid, p); 468e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT16 (cfg_info.flags, p); 469e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 470e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_cfg_start = p; 471e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 4726ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach cfg_info.flush_to_present = cfg_info.mtu_present = cfg_info.qos_present = 473e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach cfg_info.fcr_present = cfg_info.fcs_present = FALSE; 474e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 475e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach while (p < p_cfg_end) 476e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 477e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT8 (cfg_code, p); 478e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT8 (cfg_len, p); 479e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 480e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach switch (cfg_code & 0x7F) 481e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 482e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach case L2CAP_CFG_TYPE_MTU: 483e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach cfg_info.mtu_present = TRUE; 484e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT16 (cfg_info.mtu, p); 485e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach break; 486e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 487e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach case L2CAP_CFG_TYPE_FLUSH_TOUT: 488e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach cfg_info.flush_to_present = TRUE; 489e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT16 (cfg_info.flush_to, p); 490e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach break; 491e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 492e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach case L2CAP_CFG_TYPE_QOS: 493e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach cfg_info.qos_present = TRUE; 494e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT8 (cfg_info.qos.qos_flags, p); 495e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT8 (cfg_info.qos.service_type, p); 496e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT32 (cfg_info.qos.token_rate, p); 497e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT32 (cfg_info.qos.token_bucket_size, p); 498e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT32 (cfg_info.qos.peak_bandwidth, p); 499e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT32 (cfg_info.qos.latency, p); 500e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT32 (cfg_info.qos.delay_variation, p); 501e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach break; 502e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 503e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach case L2CAP_CFG_TYPE_FCR: 504e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach cfg_info.fcr_present = TRUE; 505e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT8 (cfg_info.fcr.mode, p); 506e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT8 (cfg_info.fcr.tx_win_sz, p); 507e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT8 (cfg_info.fcr.max_transmit, p); 508e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT16 (cfg_info.fcr.rtrans_tout, p); 509e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT16 (cfg_info.fcr.mon_tout, p); 510e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT16 (cfg_info.fcr.mps, p); 511e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach break; 512e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 513e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach case L2CAP_CFG_TYPE_FCS: 514e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach cfg_info.fcs_present = TRUE; 515e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT8 (cfg_info.fcs, p); 516e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach break; 517e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 518e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach case L2CAP_CFG_TYPE_EXT_FLOW: 519e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach cfg_info.ext_flow_spec_present = TRUE; 520e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT8 (cfg_info.ext_flow_spec.id, p); 521e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT8 (cfg_info.ext_flow_spec.stype, p); 522e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT16 (cfg_info.ext_flow_spec.max_sdu_size, p); 523e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT32 (cfg_info.ext_flow_spec.sdu_inter_time, p); 524e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT32 (cfg_info.ext_flow_spec.access_latency, p); 525e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT32 (cfg_info.ext_flow_spec.flush_timeout, p); 526e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach break; 527e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 528e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach default: 529e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* sanity check option length */ 530e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if ((cfg_len + L2CAP_CFG_OPTION_OVERHEAD) <= cmd_len) 531e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 532e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p += cfg_len; 533e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if ((cfg_code & 0x80) == 0) 534e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 535e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach cfg_rej_len += cfg_len + L2CAP_CFG_OPTION_OVERHEAD; 536e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach cfg_rej = TRUE; 537e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 538e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 539e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* bad length; force loop exit */ 540e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach else 541e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 542e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p = p_cfg_end; 543e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach cfg_rej = TRUE; 544e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 545e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach break; 546e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 547e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 548e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 549e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if ((p_ccb = l2cu_find_ccb_by_cid (p_lcb, lcid)) != NULL) 550e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 551e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_ccb->remote_id = id; 552e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (cfg_rej) 553e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 554e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach l2cu_send_peer_config_rej (p_ccb, p_cfg_start, (UINT16) (cmd_len - L2CAP_CONFIG_REQ_LEN), cfg_rej_len); 555e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 556e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach else 557e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 558e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach l2c_csm_execute (p_ccb, L2CEVT_L2CAP_CONFIG_REQ, &cfg_info); 559e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 560e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 561e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach else 562e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 563e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* updated spec says send command reject on invalid cid */ 564e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach l2cu_send_peer_cmd_reject (p_lcb, L2CAP_CMD_REJ_INVALID_CID, id, 0, 0); 565e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 566e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach break; 567e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 568e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach case L2CAP_CMD_CONFIG_RSP: 569e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_cfg_end = p + cmd_len; 570e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT16 (lcid, p); 571e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT16 (cfg_info.flags, p); 572e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT16 (cfg_info.result, p); 573e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 5746ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach cfg_info.flush_to_present = cfg_info.mtu_present = cfg_info.qos_present = 575e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach cfg_info.fcr_present = cfg_info.fcs_present = FALSE; 576e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 577e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach while (p < p_cfg_end) 578e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 579e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT8 (cfg_code, p); 580e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT8 (cfg_len, p); 581e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 582e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach switch (cfg_code & 0x7F) 583e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 584e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach case L2CAP_CFG_TYPE_MTU: 585e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach cfg_info.mtu_present = TRUE; 586e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT16 (cfg_info.mtu, p); 587e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach break; 588e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 589e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach case L2CAP_CFG_TYPE_FLUSH_TOUT: 590e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach cfg_info.flush_to_present = TRUE; 591e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT16 (cfg_info.flush_to, p); 592e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach break; 593e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 594e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach case L2CAP_CFG_TYPE_QOS: 595e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach cfg_info.qos_present = TRUE; 596e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT8 (cfg_info.qos.qos_flags, p); 597e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT8 (cfg_info.qos.service_type, p); 598e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT32 (cfg_info.qos.token_rate, p); 599e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT32 (cfg_info.qos.token_bucket_size, p); 600e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT32 (cfg_info.qos.peak_bandwidth, p); 601e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT32 (cfg_info.qos.latency, p); 602e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT32 (cfg_info.qos.delay_variation, p); 603e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach break; 604e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 605e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach case L2CAP_CFG_TYPE_FCR: 606e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach cfg_info.fcr_present = TRUE; 607e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT8 (cfg_info.fcr.mode, p); 608e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT8 (cfg_info.fcr.tx_win_sz, p); 609e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT8 (cfg_info.fcr.max_transmit, p); 610e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT16 (cfg_info.fcr.rtrans_tout, p); 611e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT16 (cfg_info.fcr.mon_tout, p); 612e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT16 (cfg_info.fcr.mps, p); 613e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach break; 614e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 615e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach case L2CAP_CFG_TYPE_FCS: 616e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach cfg_info.fcs_present = TRUE; 617e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT8 (cfg_info.fcs, p); 618e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach break; 619e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 620e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach case L2CAP_CFG_TYPE_EXT_FLOW: 621e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach cfg_info.ext_flow_spec_present = TRUE; 622e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT8 (cfg_info.ext_flow_spec.id, p); 623e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT8 (cfg_info.ext_flow_spec.stype, p); 624e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT16 (cfg_info.ext_flow_spec.max_sdu_size, p); 625e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT32 (cfg_info.ext_flow_spec.sdu_inter_time, p); 626e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT32 (cfg_info.ext_flow_spec.access_latency, p); 627e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT32 (cfg_info.ext_flow_spec.flush_timeout, p); 628e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach break; 629e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 630e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 631e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 632e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if ((p_ccb = l2cu_find_ccb_by_cid (p_lcb, lcid)) != NULL) 633e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 634e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (p_ccb->local_id != id) 635e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 636e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach L2CAP_TRACE_WARNING2 ("L2CAP - cfg rsp - bad ID. Exp: %d Got: %d", 637e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_ccb->local_id, id); 638e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach break; 639e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 640e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if ( (cfg_info.result == L2CAP_CFG_OK) || (cfg_info.result == L2CAP_CFG_PENDING) ) 641e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach l2c_csm_execute (p_ccb, L2CEVT_L2CAP_CONFIG_RSP, &cfg_info); 642e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach else 643e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach l2c_csm_execute (p_ccb, L2CEVT_L2CAP_CONFIG_RSP_NEG, &cfg_info); 644e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 645e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach else 646e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 647e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach L2CAP_TRACE_WARNING1 ("L2CAP - rcvd cfg rsp for unknown CID: 0x%04x", lcid); 648e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 649e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach break; 650e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 651e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 652e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach case L2CAP_CMD_DISC_REQ: 653e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT16 (lcid, p); 654e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT16 (rcid, p); 655e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 656e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if ((p_ccb = l2cu_find_ccb_by_cid (p_lcb, lcid)) != NULL) 657e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 658e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (p_ccb->remote_cid == rcid) 659e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 660e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_ccb->remote_id = id; 661e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach l2c_csm_execute (p_ccb, L2CEVT_L2CAP_DISCONNECT_REQ, &con_info); 662e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 663e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 664e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach else 665e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach l2cu_send_peer_disc_rsp (p_lcb, id, lcid, rcid); 666e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 667e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach break; 668e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 669e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach case L2CAP_CMD_DISC_RSP: 670e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT16 (rcid, p); 671e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT16 (lcid, p); 672e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 673e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if ((p_ccb = l2cu_find_ccb_by_cid (p_lcb, lcid)) != NULL) 674e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 675e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if ((p_ccb->remote_cid == rcid) && (p_ccb->local_id == id)) 676e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 677e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach l2c_csm_execute (p_ccb, L2CEVT_L2CAP_DISCONNECT_RSP, &con_info); 678e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 679e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 680e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach break; 681e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 682e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach case L2CAP_CMD_ECHO_REQ: 683e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 684e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#if (L2CAP_ENHANCED_FEATURES != 0) 685e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (!l2cu_check_feature_req (p_lcb, id, p, cmd_len)) 686e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 687e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (cmd_len < (btu_cb.hcit_acl_pkt_size - L2CAP_PKT_OVERHEAD 688e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach - L2CAP_CMD_OVERHEAD 689e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach - L2CAP_ECHO_RSP_LEN 690e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach - HCI_DATA_PREAMBLE_SIZE)) 691e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 692e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach l2cu_send_peer_echo_rsp (p_lcb, id, p, cmd_len); 693e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 694e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach else 695e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 696e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach l2cu_send_peer_echo_rsp (p_lcb, id, NULL, 0); 697e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 698e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 699e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#else 700e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach l2cu_send_peer_echo_rsp (p_lcb, id, NULL, 0); 701e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#endif 702e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach break; 7036ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach 704e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach case L2CAP_CMD_ECHO_RSP: 705e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#if (L2CAP_ENHANCED_FEATURES != 0) 706e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach l2cu_check_feature_rsp (p_lcb, id, p, cmd_len); 707e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#endif 708e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (p_lcb->p_echo_rsp_cb) 709e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 710e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach tL2CA_ECHO_RSP_CB *p_cb = p_lcb->p_echo_rsp_cb; 711e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 712e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* Zero out the callback in case app immediately calls us again */ 713e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_lcb->p_echo_rsp_cb = NULL; 714e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 715e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach (*p_cb) (L2CAP_PING_RESULT_OK); 716e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 717e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach break; 718e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 719e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach case L2CAP_CMD_INFO_REQ: 720e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT16 (info_type, p); 721e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach l2cu_send_peer_info_rsp (p_lcb, id, info_type); 722e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach break; 723e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 724e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach case L2CAP_CMD_INFO_RSP: 725e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* Stop the link connect timer if sent before L2CAP connection is up */ 726e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (p_lcb->w4_info_rsp) 727e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 728e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach btu_stop_timer (&p_lcb->info_timer_entry); 729e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_lcb->w4_info_rsp = FALSE; 730e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 731e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 732e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT16 (info_type, p); 733e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT16 (result, p); 734e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 735e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_lcb->info_rx_bits |= (1 << info_type); 736e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 7376ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach if ( (info_type == L2CAP_EXTENDED_FEATURES_INFO_TYPE) 738e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach && (result == L2CAP_INFO_RESP_RESULT_SUCCESS) ) 739e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 740e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT32( p_lcb->peer_ext_fea, p ); 741e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 742e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#if (L2CAP_NUM_FIXED_CHNLS > 0) 743e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (p_lcb->peer_ext_fea & L2CAP_EXTFEA_FIXED_CHNLS) 744e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 745e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach l2cu_send_peer_info_req (p_lcb, L2CAP_FIXED_CHANNELS_INFO_TYPE); 746e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach break; 747e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 748e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach else 749e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 750e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach l2cu_process_fixed_chnl_resp (p_lcb); 751e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 752e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#endif 753e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 754e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 755e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 756e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#if (L2CAP_NUM_FIXED_CHNLS > 0) 757e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (info_type == L2CAP_FIXED_CHANNELS_INFO_TYPE) 758e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 759e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (result == L2CAP_INFO_RESP_RESULT_SUCCESS) 760e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 761e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach memcpy (p_lcb->peer_chnl_mask, p, L2CAP_FIXED_CHNL_ARRAY_SIZE); 762e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 763e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 764e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach l2cu_process_fixed_chnl_resp (p_lcb); 765e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 766e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#endif 767e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#if (L2CAP_UCD_INCLUDED == TRUE) 768e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach else if (info_type == L2CAP_CONNLESS_MTU_INFO_TYPE) 769e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 770e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (result == L2CAP_INFO_RESP_RESULT_SUCCESS) 771e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 772e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach STREAM_TO_UINT16 (p_lcb->ucd_mtu, p); 773e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 774e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 775e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#endif 776e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 777e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach ci.status = HCI_SUCCESS; 778e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach memcpy (ci.bd_addr, p_lcb->remote_bd_addr, sizeof(BD_ADDR)); 779e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_ccb->p_next_ccb) 780e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 781e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach l2c_csm_execute (p_ccb, L2CEVT_L2CAP_INFO_RSP, &ci); 782e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 783e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach break; 784e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 785e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach default: 786e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach L2CAP_TRACE_WARNING1 ("L2CAP - bad cmd code: %d", cmd_code); 787e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach l2cu_send_peer_cmd_reject (p_lcb, L2CAP_CMD_REJ_NOT_UNDERSTOOD, id, 0, 0); 788e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach return; 789e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 790e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 791e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach} 792e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 793e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/******************************************************************************* 794e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 795e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function l2c_process_held_packets 796e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 797e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Description This function processes any L2CAP packets that arrived before 7986ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach** the HCI connection complete arrived. It is a work around for 799e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** badly behaved controllers. 800e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 801e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Returns void 802e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 803e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/ 804e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbachvoid l2c_process_held_packets (BOOLEAN timed_out) 805e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{ 806e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach BT_HDR *p_buf, *p_buf1; 807e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach BUFFER_Q *p_rcv_hold_q = &l2cb.rcv_hold_q; 808e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 809e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (!p_rcv_hold_q->count) 810e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach return; 811e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 812e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (!timed_out) 813e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 814e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach btu_stop_timer(&l2cb.rcv_hold_tle); 815e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach L2CAP_TRACE_WARNING0("L2CAP HOLD CONTINUE"); 816e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 817e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach else 818e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 819e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach L2CAP_TRACE_WARNING0("L2CAP HOLD TIMEOUT"); 820e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 821e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 822e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* Update the timeouts in the hold queue */ 823e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach for (p_buf = (BT_HDR *)GKI_getfirst (p_rcv_hold_q); p_buf; p_buf = p_buf1) 824e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 825e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_buf1 = (BT_HDR *)GKI_getnext (p_buf); 826e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (!timed_out || (!p_buf->layer_specific) || (--p_buf->layer_specific == 0)) 827e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 828e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach GKI_remove_from_queue (p_rcv_hold_q, p_buf); 829e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_buf->layer_specific = 0xFFFF; 830e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach l2c_rcv_acl_data (p_buf); 831e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 832e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 833e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 834e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* If anyone still in the queue, restart the timeout */ 835e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (p_rcv_hold_q->count) 836e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach btu_start_timer (&l2cb.rcv_hold_tle, BTU_TTYPE_L2CAP_HOLD, BT_1SEC_TIMEOUT); 837e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach} 838e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 839e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 840e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/******************************************************************************* 841e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 842e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function l2c_init 843e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 844e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Description This function is called once at startup to initialize 845e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** all the L2CAP structures 846e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 847e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Returns void 848e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 849e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/ 850e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbachvoid l2c_init (void) 851e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{ 852e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach INT16 xx; 853e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 854e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach memset (&l2cb, 0, sizeof (tL2C_CB)); 855e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* the psm is increased by 2 before being used */ 856e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach l2cb.dyn_psm = 0xFFF; 857e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 858e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* Put all the channel control blocks on the free queue */ 859e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach for (xx = 0; xx < MAX_L2CAP_CHANNELS - 1; xx++) 860e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 861e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach l2cb.ccb_pool[xx].p_next_ccb = &l2cb.ccb_pool[xx + 1]; 862e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 863e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 864e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE) 865e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* it will be set to L2CAP_PKT_START_NON_FLUSHABLE if controller supports */ 866e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach l2cb.non_flushable_pbf = L2CAP_PKT_START << L2CAP_PKT_TYPE_SHIFT; 867e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#endif 868e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 869e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 870e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach l2cb.p_free_ccb_first = &l2cb.ccb_pool[0]; 871e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach l2cb.p_free_ccb_last = &l2cb.ccb_pool[MAX_L2CAP_CHANNELS - 1]; 872e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 873e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#ifdef L2CAP_DESIRED_LINK_ROLE 874e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach l2cb.desire_role = L2CAP_DESIRED_LINK_ROLE; 875e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#else 876e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach l2cb.desire_role = HCI_ROLE_SLAVE; 877e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#endif 878e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 879e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* Set the default idle timeout */ 880e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach l2cb.idle_timeout = L2CAP_LINK_INACTIVITY_TOUT; 881e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 882e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#if defined(L2CAP_INITIAL_TRACE_LEVEL) 883e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach l2cb.l2cap_trace_level = L2CAP_INITIAL_TRACE_LEVEL; 884e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#else 885e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach l2cb.l2cap_trace_level = BT_TRACE_LEVEL_NONE; /* No traces */ 886e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#endif 887e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 888e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#if L2CAP_CONFORMANCE_TESTING == TRUE 889e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* Conformance testing needs a dynamic response */ 890e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach l2cb.test_info_resp = L2CAP_EXTFEA_SUPPORTED_MASK; 891e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#endif 892e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 893e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* Number of ACL buffers to use for high priority channel */ 894e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#if (defined(L2CAP_HIGH_PRI_CHAN_QUOTA_IS_CONFIGURABLE) && (L2CAP_HIGH_PRI_CHAN_QUOTA_IS_CONFIGURABLE == TRUE)) 895e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach l2cb.high_pri_min_xmit_quota = L2CAP_HIGH_PRI_MIN_XMIT_QUOTA; 896e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#endif 897e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 898e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach} 899e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 900e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/******************************************************************************* 901e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 902e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function l2c_process_timeout 903e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 904e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Description This function is called when an L2CAP-related timeout occurs 905e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 906e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Returns void 907e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 908e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/ 909e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbachvoid l2c_process_timeout (TIMER_LIST_ENT *p_tle) 910e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{ 911e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* What type of timeout ? */ 912e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach switch (p_tle->event) 913e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 914e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach case BTU_TTYPE_L2CAP_LINK: 915e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach l2c_link_timeout ((tL2C_LCB *)p_tle->param); 916e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach break; 917e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 918e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach case BTU_TTYPE_L2CAP_CHNL: 919e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach l2c_csm_execute (((tL2C_CCB *)p_tle->param), L2CEVT_TIMEOUT, NULL); 920e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach break; 921e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 922e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach case BTU_TTYPE_L2CAP_FCR_ACK: 923e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach l2c_csm_execute (((tL2C_CCB *)p_tle->param), L2CEVT_ACK_TIMEOUT, NULL); 924e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach break; 925e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 926e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach case BTU_TTYPE_L2CAP_HOLD: 927e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* Update the timeouts in the hold queue */ 928e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach l2c_process_held_packets(TRUE); 929e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach break; 930e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 931e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach case BTU_TTYPE_L2CAP_INFO: 932e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach l2c_info_timeout((tL2C_LCB *)p_tle->param); 933e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach break; 934e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 935e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 936e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach} 937e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 938e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/******************************************************************************* 939e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 940e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function l2c_data_write 941e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 942e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Description API functions call this function to write data. 943e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 944e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Returns L2CAP_DW_SUCCESS, if data accepted, else FALSE 945e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** L2CAP_DW_CONGESTED, if data accepted and the channel is congested 946e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** L2CAP_DW_FAILED, if error 947e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** 948e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/ 949e448862a47c08eb23185aaed574b39264f5005fcAndre EisenbachUINT8 l2c_data_write (UINT16 cid, BT_HDR *p_data, UINT16 flags) 950e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{ 951e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach tL2C_CCB *p_ccb; 952e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 953e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* Find the channel control block. We don't know the link it is on. */ 954e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if ((p_ccb = l2cu_find_ccb_by_cid (NULL, cid)) == NULL) 955e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 956e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach L2CAP_TRACE_WARNING1 ("L2CAP - no CCB for L2CA_DataWrite, CID: %d", cid); 957e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach GKI_freebuf (p_data); 958e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach return (L2CAP_DW_FAILED); 959e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 960e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 9616ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach#ifndef TESTER /* Tester may send any amount of data. otherwise sending message 962e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach bigger than mtu size of peer is a violation of protocol */ 9636ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach if (p_data->len > p_ccb->peer_cfg.mtu) 964e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 965e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach L2CAP_TRACE_WARNING1 ("L2CAP - CID: 0x%04x cannot send message bigger than peer's mtu size", cid); 966e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach GKI_freebuf (p_data); 967e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach return (L2CAP_DW_FAILED); 968e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 969e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#endif 970e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 971e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* channel based, packet based flushable or non-flushable */ 972e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_data->layer_specific = flags; 973e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 974e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach /* If already congested, do not accept any more packets */ 975e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (p_ccb->cong_sent) 976e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach { 977e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach L2CAP_TRACE_ERROR3 ("L2CAP - CID: 0x%04x cannot send, already congested xmit_hold_q.count: %u buff_quota: %u", 978e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach p_ccb->local_cid, p_ccb->xmit_hold_q.count, p_ccb->buff_quota); 979e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 980e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach GKI_freebuf (p_data); 981e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach return (L2CAP_DW_FAILED); 982e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach } 983e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 984e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach l2c_csm_execute (p_ccb, L2CEVT_L2CA_DATA_WRITE, p_data); 985e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 986e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach if (p_ccb->cong_sent) 987e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach return (L2CAP_DW_CONGESTED); 988e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 989e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach return (L2CAP_DW_SUCCESS); 990e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach} 991e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach 992