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 "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 */ 42 void bta_ag_port_cback_1(UINT32 code, UINT16 port_handle); 43 void bta_ag_port_cback_2(UINT32 code, UINT16 port_handle); 44 void bta_ag_port_cback_3(UINT32 code, UINT16 port_handle); 45 46 void bta_ag_mgmt_cback_1(UINT32 code, UINT16 port_handle); 47 void bta_ag_mgmt_cback_2(UINT32 code, UINT16 port_handle); 48 void bta_ag_mgmt_cback_3(UINT32 code, UINT16 port_handle); 49 50 int bta_ag_data_cback_1(UINT16 port_handle, void *p_data, UINT16 len); 51 int bta_ag_data_cback_2(UINT16 port_handle, void *p_data, UINT16 len); 52 int bta_ag_data_cback_3(UINT16 port_handle, void *p_data, UINT16 len); 53 54 /* rfcomm callback function tables */ 55 typedef tPORT_CALLBACK *tBTA_AG_PORT_CBACK; 56 const 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 63 const 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 70 typedef tPORT_DATA_CALLBACK *tBTA_AG_DATA_CBACK; 71 const 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 *******************************************************************************/ 88 static 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 *) GKI_getbuf(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 *******************************************************************************/ 123 static 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 *) GKI_getbuf(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 *******************************************************************************/ 197 static 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 *******************************************************************************/ 218 void bta_ag_mgmt_cback_1(UINT32 code, UINT16 handle) {bta_ag_mgmt_cback(code, handle, 1);} 219 void bta_ag_mgmt_cback_2(UINT32 code, UINT16 handle) {bta_ag_mgmt_cback(code, handle, 2);} 220 void bta_ag_mgmt_cback_3(UINT32 code, UINT16 handle) {bta_ag_mgmt_cback(code, handle, 3);} 221 void bta_ag_port_cback_1(UINT32 code, UINT16 handle) {bta_ag_port_cback(code, handle, 1);} 222 void bta_ag_port_cback_2(UINT32 code, UINT16 handle) {bta_ag_port_cback(code, handle, 2);} 223 void 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 *******************************************************************************/ 236 int 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 } 240 int 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 } 244 int 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 *******************************************************************************/ 259 void 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 *******************************************************************************/ 283 void 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 *******************************************************************************/ 324 void 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 *******************************************************************************/ 350 BOOLEAN 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 *******************************************************************************/ 374 void 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 *******************************************************************************/ 403 void 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 *) GKI_getbuf(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