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