1/****************************************************************************** 2 * 3 * Copyright (C) 2004-2012 Broadcom Corporation 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at: 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 ******************************************************************************/ 18 19/****************************************************************************** 20 * 21 * This file contains the audio gateway functions controlling the RFCOMM 22 * connections. 23 * 24 ******************************************************************************/ 25 26#include <string.h> 27#include "bta_api.h" 28#include "bta_sys.h" 29#include "bta_ag_api.h" 30#include "bta_ag_int.h" 31#include "bta_ag_co.h" 32#include "btm_api.h" 33#include "port_api.h" 34#include "rfcdefs.h" 35#include "gki.h" 36#include "bd.h" 37#include "utl.h" 38 39/* Event mask for RfCOMM port callback */ 40#define BTA_AG_PORT_EV_MASK PORT_EV_RXCHAR 41 42/* each scb has its own rfcomm callbacks */ 43void bta_ag_port_cback_1(UINT32 code, UINT16 port_handle); 44void bta_ag_port_cback_2(UINT32 code, UINT16 port_handle); 45void bta_ag_port_cback_3(UINT32 code, UINT16 port_handle); 46 47void bta_ag_mgmt_cback_1(UINT32 code, UINT16 port_handle); 48void bta_ag_mgmt_cback_2(UINT32 code, UINT16 port_handle); 49void bta_ag_mgmt_cback_3(UINT32 code, UINT16 port_handle); 50 51int bta_ag_data_cback_1(UINT16 port_handle, void *p_data, UINT16 len); 52int bta_ag_data_cback_2(UINT16 port_handle, void *p_data, UINT16 len); 53int bta_ag_data_cback_3(UINT16 port_handle, void *p_data, UINT16 len); 54 55/* rfcomm callback function tables */ 56typedef tPORT_CALLBACK *tBTA_AG_PORT_CBACK; 57const tBTA_AG_PORT_CBACK bta_ag_port_cback_tbl[] = 58{ 59 bta_ag_port_cback_1, 60 bta_ag_port_cback_2, 61 bta_ag_port_cback_3 62}; 63 64const tBTA_AG_PORT_CBACK bta_ag_mgmt_cback_tbl[] = 65{ 66 bta_ag_mgmt_cback_1, 67 bta_ag_mgmt_cback_2, 68 bta_ag_mgmt_cback_3 69}; 70 71typedef tPORT_DATA_CALLBACK *tBTA_AG_DATA_CBACK; 72const tBTA_AG_DATA_CBACK bta_ag_data_cback_tbl[] = 73{ 74 bta_ag_data_cback_1, 75 bta_ag_data_cback_2, 76 bta_ag_data_cback_3 77}; 78 79/******************************************************************************* 80** 81** Function bta_ag_port_cback 82** 83** Description RFCOMM Port callback 84** 85** 86** Returns void 87** 88*******************************************************************************/ 89static void bta_ag_port_cback(UINT32 code, UINT16 port_handle, UINT16 handle) 90{ 91 BT_HDR *p_buf; 92 tBTA_AG_SCB *p_scb; 93 UNUSED(code); 94 95 if ((p_scb = bta_ag_scb_by_idx(handle)) != NULL) 96 { 97 /* ignore port events for port handles other than connected handle */ 98 if (port_handle != p_scb->conn_handle) 99 { 100 APPL_TRACE_DEBUG("ag_port_cback ignoring handle:%d conn_handle = %d other handle = %d", 101 port_handle, p_scb->conn_handle, handle); 102 return; 103 } 104 105 if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL) 106 { 107 p_buf->event = BTA_AG_RFC_DATA_EVT; 108 p_buf->layer_specific = handle; 109 bta_sys_sendmsg(p_buf); 110 } 111 } 112} 113 114/******************************************************************************* 115** 116** Function bta_ag_mgmt_cback 117** 118** Description RFCOMM management callback 119** 120** 121** Returns void 122** 123*******************************************************************************/ 124static void bta_ag_mgmt_cback(UINT32 code, UINT16 port_handle, UINT16 handle) 125{ 126 tBTA_AG_RFC *p_buf; 127 tBTA_AG_SCB *p_scb; 128 UINT16 event; 129 UINT8 i; 130 BOOLEAN found_handle = FALSE; 131 132 APPL_TRACE_DEBUG("ag_mgmt_cback : code = %d, port_handle = %d, handle = %d", 133 code, port_handle, handle); 134 135 if ((p_scb = bta_ag_scb_by_idx(handle)) != NULL) 136 { 137 /* ignore close event for port handles other than connected handle */ 138 if ((code != PORT_SUCCESS) && (port_handle != p_scb->conn_handle)) 139 { 140 APPL_TRACE_DEBUG("ag_mgmt_cback ignoring handle:%d", port_handle); 141 return; 142 } 143 144 if (code == PORT_SUCCESS) 145 { 146 if (p_scb->conn_handle) /* Outgoing connection */ 147 { 148 if (port_handle == p_scb->conn_handle) 149 found_handle = TRUE; 150 } 151 else /* Incoming connection */ 152 { 153 for (i = 0; i < BTA_AG_NUM_IDX; i++) 154 { 155 if (port_handle == p_scb->serv_handle[i]) 156 found_handle = TRUE; 157 } 158 } 159 160 if (!found_handle) 161 { 162 APPL_TRACE_ERROR ("bta_ag_mgmt_cback: PORT_SUCCESS, ignoring handle = %d", port_handle); 163 return; 164 } 165 166 event = BTA_AG_RFC_OPEN_EVT; 167 } 168 /* distinguish server close events */ 169 else if (port_handle == p_scb->conn_handle) 170 { 171 event = BTA_AG_RFC_CLOSE_EVT; 172 } 173 else 174 { 175 event = BTA_AG_RFC_SRV_CLOSE_EVT; 176 } 177 178 if ((p_buf = (tBTA_AG_RFC *) GKI_getbuf(sizeof(tBTA_AG_RFC))) != NULL) 179 { 180 p_buf->hdr.event = event; 181 p_buf->hdr.layer_specific = handle; 182 p_buf->port_handle = port_handle; 183 bta_sys_sendmsg(p_buf); 184 } 185 } 186} 187 188/******************************************************************************* 189** 190** Function bta_ag_data_cback 191** 192** Description RFCOMM data callback 193** 194** 195** Returns void 196** 197*******************************************************************************/ 198static int bta_ag_data_cback(UINT16 port_handle, void *p_data, UINT16 len, UINT16 handle) 199{ 200 UNUSED(port_handle); 201 202 /* call data call-out directly */ 203 bta_ag_co_tx_write(handle, (UINT8 *) p_data, len); 204 return 0; 205} 206 207/******************************************************************************* 208** 209** Function bta_ag_port_cback_1 to 3 210** bta_ag_mgmt_cback_1 to 3 211** 212** Description RFCOMM callback functions. This is an easy way to 213** distinguish scb from the callback. 214** 215** 216** Returns void 217** 218*******************************************************************************/ 219void bta_ag_mgmt_cback_1(UINT32 code, UINT16 handle) {bta_ag_mgmt_cback(code, handle, 1);} 220void bta_ag_mgmt_cback_2(UINT32 code, UINT16 handle) {bta_ag_mgmt_cback(code, handle, 2);} 221void bta_ag_mgmt_cback_3(UINT32 code, UINT16 handle) {bta_ag_mgmt_cback(code, handle, 3);} 222void bta_ag_port_cback_1(UINT32 code, UINT16 handle) {bta_ag_port_cback(code, handle, 1);} 223void bta_ag_port_cback_2(UINT32 code, UINT16 handle) {bta_ag_port_cback(code, handle, 2);} 224void bta_ag_port_cback_3(UINT32 code, UINT16 handle) {bta_ag_port_cback(code, handle, 3);} 225 226/******************************************************************************* 227** 228** Function bta_ag_data_cback_1 to 3 229** 230** Description RFCOMM data callback functions. This is an easy way to 231** distinguish scb from the callback. 232** 233** 234** Returns void 235** 236*******************************************************************************/ 237int bta_ag_data_cback_1(UINT16 port_handle, void *p_data, UINT16 len) 238{ 239 return bta_ag_data_cback(port_handle, p_data, len, 1); 240} 241int bta_ag_data_cback_2(UINT16 port_handle, void *p_data, UINT16 len) 242{ 243 return bta_ag_data_cback(port_handle, p_data, len, 2); 244} 245int bta_ag_data_cback_3(UINT16 port_handle, void *p_data, UINT16 len) 246{ 247 return bta_ag_data_cback(port_handle, p_data, len, 3); 248} 249 250/******************************************************************************* 251** 252** Function bta_ag_setup_port 253** 254** Description Setup RFCOMM port for use by AG. 255** 256** 257** Returns void 258** 259*******************************************************************************/ 260void bta_ag_setup_port(tBTA_AG_SCB *p_scb, UINT16 handle) 261{ 262 UINT16 i = bta_ag_scb_to_idx(p_scb) - 1; 263 264 /* set up data callback if using pass through mode */ 265 if (bta_ag_cb.parse_mode == BTA_AG_PASS_THROUGH) 266 { 267 PORT_SetDataCallback(handle, bta_ag_data_cback_tbl[i]); 268 } 269 270 PORT_SetEventMask(handle, BTA_AG_PORT_EV_MASK); 271 PORT_SetEventCallback(handle, bta_ag_port_cback_tbl[i]); 272} 273 274/******************************************************************************* 275** 276** Function bta_ag_start_servers 277** 278** Description Setup RFCOMM servers for use by AG. 279** 280** 281** Returns void 282** 283*******************************************************************************/ 284void bta_ag_start_servers(tBTA_AG_SCB *p_scb, tBTA_SERVICE_MASK services) 285{ 286 int i; 287 int bta_ag_port_status; 288 289 services >>= BTA_HSP_SERVICE_ID; 290 for (i = 0; i < BTA_AG_NUM_IDX && services != 0; i++, services >>= 1) 291 { 292 /* if service is set in mask */ 293 if (services & 1) 294 { 295 BTM_SetSecurityLevel(FALSE, "", bta_ag_sec_id[i], p_scb->serv_sec_mask, 296 BT_PSM_RFCOMM, BTM_SEC_PROTO_RFCOMM, bta_ag_cb.profile[i].scn); 297 298 bta_ag_port_status = RFCOMM_CreateConnection(bta_ag_uuid[i], bta_ag_cb.profile[i].scn, 299 TRUE, BTA_AG_MTU, (UINT8 *) bd_addr_any, &(p_scb->serv_handle[i]), 300 bta_ag_mgmt_cback_tbl[bta_ag_scb_to_idx(p_scb) - 1]); 301 302 if( bta_ag_port_status == PORT_SUCCESS ) 303 { 304 bta_ag_setup_port(p_scb, p_scb->serv_handle[i]); 305 } 306 else 307 { 308 /* TODO: CR#137125 to handle to error properly */ 309 APPL_TRACE_DEBUG("bta_ag_start_servers: RFCOMM_CreateConnection returned error:%d", bta_ag_port_status); 310 } 311 } 312 } 313} 314 315/******************************************************************************* 316** 317** Function bta_ag_close_servers 318** 319** Description Close RFCOMM servers port for use by AG. 320** 321** 322** Returns void 323** 324*******************************************************************************/ 325void bta_ag_close_servers(tBTA_AG_SCB *p_scb, tBTA_SERVICE_MASK services) 326{ 327 int i; 328 329 services >>= BTA_HSP_SERVICE_ID; 330 for (i = 0; i < BTA_AG_NUM_IDX && services != 0; i++, services >>= 1) 331 { 332 /* if service is set in mask */ 333 if (services & 1) 334 { 335 RFCOMM_RemoveServer(p_scb->serv_handle[i]); 336 p_scb->serv_handle[i] = 0; 337 } 338 } 339} 340 341/******************************************************************************* 342** 343** Function bta_ag_is_server_closed 344** 345** Description Returns TRUE if all servers are closed. 346** 347** 348** Returns TRUE if all servers are closed, FALSE otherwise 349** 350*******************************************************************************/ 351BOOLEAN bta_ag_is_server_closed (tBTA_AG_SCB *p_scb) 352{ 353 UINT8 xx; 354 BOOLEAN is_closed = TRUE; 355 356 for (xx = 0; xx < BTA_AG_NUM_IDX; xx++) 357 { 358 if (p_scb->serv_handle[xx] != 0) 359 is_closed = FALSE; 360 } 361 362 return is_closed; 363} 364 365/******************************************************************************* 366** 367** Function bta_ag_rfc_do_open 368** 369** Description Open an RFCOMM connection to the peer device. 370** 371** 372** Returns void 373** 374*******************************************************************************/ 375void bta_ag_rfc_do_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) 376{ 377 BTM_SetSecurityLevel(TRUE, "", bta_ag_sec_id[p_scb->conn_service], 378 p_scb->cli_sec_mask, BT_PSM_RFCOMM, BTM_SEC_PROTO_RFCOMM, p_scb->peer_scn); 379 380 if (RFCOMM_CreateConnection(bta_ag_uuid[p_scb->conn_service], p_scb->peer_scn, 381 FALSE, BTA_AG_MTU, p_scb->peer_addr, &(p_scb->conn_handle), 382 bta_ag_mgmt_cback_tbl[bta_ag_scb_to_idx(p_scb) - 1]) == PORT_SUCCESS) 383 { 384 bta_ag_setup_port(p_scb, p_scb->conn_handle); 385 APPL_TRACE_DEBUG("bta_ag_rfc_do_open : conn_handle = %d", p_scb->conn_handle); 386 } 387 /* RFCOMM create connection failed; send ourselves RFCOMM close event */ 388 else 389 { 390 bta_ag_sm_execute(p_scb, BTA_AG_RFC_CLOSE_EVT, p_data); 391 } 392} 393 394/******************************************************************************* 395** 396** Function bta_ag_rfc_do_close 397** 398** Description Close RFCOMM connection. 399** 400** 401** Returns void 402** 403*******************************************************************************/ 404void bta_ag_rfc_do_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) 405{ 406 tBTA_AG_RFC *p_buf; 407 UNUSED(p_data); 408 409 if (p_scb->conn_handle) 410 { 411 RFCOMM_RemoveConnection(p_scb->conn_handle); 412 } 413 else 414 { 415 /* Close API was called while AG is in Opening state. */ 416 /* Need to trigger the state machine to send callback to the app */ 417 /* and move back to INIT state. */ 418 if ((p_buf = (tBTA_AG_RFC *) GKI_getbuf(sizeof(tBTA_AG_RFC))) != NULL) 419 { 420 p_buf->hdr.event = BTA_AG_RFC_CLOSE_EVT; 421 p_buf->hdr.layer_specific = bta_ag_scb_to_idx(p_scb); 422 bta_sys_sendmsg(p_buf); 423 } 424 425 /* Cancel SDP if it had been started. */ 426 /* 427 if(p_scb->p_disc_db) 428 { 429 (void)SDP_CancelServiceSearch (p_scb->p_disc_db); 430 } 431 */ 432 } 433 434#ifdef _WIN32_WCE 435 { 436 /* Windows versions of RFCOMM does NOT generate a closed callback when we close */ 437 tPORT_CALLBACK *rfc_mgmt_cback = bta_ag_mgmt_cback_tbl[bta_ag_scb_to_idx(p_scb) - 1]; 438 439 if (rfc_mgmt_cback) 440 { 441 (rfc_mgmt_cback)(PORT_CLOSED, p_scb->conn_handle); 442 } 443 } 444#endif 445} 446 447