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