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 */ 43 void bta_ag_port_cback_1(UINT32 code, UINT16 port_handle); 44 void bta_ag_port_cback_2(UINT32 code, UINT16 port_handle); 45 void bta_ag_port_cback_3(UINT32 code, UINT16 port_handle); 46 47 void bta_ag_mgmt_cback_1(UINT32 code, UINT16 port_handle); 48 void bta_ag_mgmt_cback_2(UINT32 code, UINT16 port_handle); 49 void bta_ag_mgmt_cback_3(UINT32 code, UINT16 port_handle); 50 51 int bta_ag_data_cback_1(UINT16 port_handle, void *p_data, UINT16 len); 52 int bta_ag_data_cback_2(UINT16 port_handle, void *p_data, UINT16 len); 53 int bta_ag_data_cback_3(UINT16 port_handle, void *p_data, UINT16 len); 54 55 /* rfcomm callback function tables */ 56 typedef tPORT_CALLBACK *tBTA_AG_PORT_CBACK; 57 const 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 64 const 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 71 typedef tPORT_DATA_CALLBACK *tBTA_AG_DATA_CBACK; 72 const 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 *******************************************************************************/ 89 static 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 *******************************************************************************/ 124 static 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 *******************************************************************************/ 198 static 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 *******************************************************************************/ 219 void bta_ag_mgmt_cback_1(UINT32 code, UINT16 handle) {bta_ag_mgmt_cback(code, handle, 1);} 220 void bta_ag_mgmt_cback_2(UINT32 code, UINT16 handle) {bta_ag_mgmt_cback(code, handle, 2);} 221 void bta_ag_mgmt_cback_3(UINT32 code, UINT16 handle) {bta_ag_mgmt_cback(code, handle, 3);} 222 void bta_ag_port_cback_1(UINT32 code, UINT16 handle) {bta_ag_port_cback(code, handle, 1);} 223 void bta_ag_port_cback_2(UINT32 code, UINT16 handle) {bta_ag_port_cback(code, handle, 2);} 224 void 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 *******************************************************************************/ 237 int 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 } 241 int 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 } 245 int 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 *******************************************************************************/ 260 void 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 *******************************************************************************/ 284 void 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 *******************************************************************************/ 325 void 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 *******************************************************************************/ 351 BOOLEAN 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 *******************************************************************************/ 375 void 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 *******************************************************************************/ 404 void 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