1 /****************************************************************************** 2 * 3 * Copyright (c) 2014 The Android Open Source Project 4 * Copyright (C) 2004-2012 Broadcom Corporation 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at: 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 * 18 ******************************************************************************/ 19 20 /****************************************************************************** 21 * 22 * This file contains the audio gateway functions controlling the RFCOMM 23 * connections. 24 * 25 ******************************************************************************/ 26 27 #include <string.h> 28 #include "bta_api.h" 29 #include "bta_hf_client_int.h" 30 #include "port_api.h" 31 #include "bt_utils.h" 32 33 /******************************************************************************* 34 ** 35 ** Function bta_hf_client_port_cback 36 ** 37 ** Description RFCOMM Port callback 38 ** 39 ** 40 ** Returns void 41 ** 42 *******************************************************************************/ 43 static void bta_hf_client_port_cback(UINT32 code, UINT16 port_handle) 44 { 45 BT_HDR *p_buf; 46 UNUSED(code); 47 48 /* ignore port events for port handles other than connected handle */ 49 if (port_handle != bta_hf_client_cb.scb.conn_handle) 50 { 51 APPL_TRACE_DEBUG("bta_hf_client_port_cback ignoring handle:%d conn_handle = %d", 52 port_handle, bta_hf_client_cb.scb.conn_handle); 53 return; 54 } 55 56 if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL) 57 { 58 p_buf->event = BTA_HF_CLIENT_RFC_DATA_EVT; 59 bta_sys_sendmsg(p_buf); 60 } 61 } 62 63 /******************************************************************************* 64 ** 65 ** Function bta_hf_client_mgmt_cback 66 ** 67 ** Description RFCOMM management callback 68 ** 69 ** 70 ** Returns void 71 ** 72 *******************************************************************************/ 73 static void bta_hf_client_mgmt_cback(UINT32 code, UINT16 port_handle) 74 { 75 tBTA_HF_CLIENT_RFC *p_buf; 76 UINT16 event; 77 78 APPL_TRACE_DEBUG("bta_hf_client_mgmt_cback : code = %d, port_handle = %d, conn_handle = %d, serv_handle = %d", 79 code, port_handle, bta_hf_client_cb.scb.conn_handle, bta_hf_client_cb.scb.serv_handle); 80 81 /* ignore close event for port handles other than connected handle */ 82 if ((code != PORT_SUCCESS) && (port_handle != bta_hf_client_cb.scb.conn_handle)) 83 { 84 APPL_TRACE_DEBUG("bta_hf_client_mgmt_cback ignoring handle:%d", port_handle); 85 return; 86 } 87 88 if (code == PORT_SUCCESS) 89 { 90 if ((bta_hf_client_cb.scb.conn_handle && (port_handle == bta_hf_client_cb.scb.conn_handle)) || /* outgoing connection */ 91 (port_handle == bta_hf_client_cb.scb.serv_handle)) /* incoming connection */ 92 { 93 event = BTA_HF_CLIENT_RFC_OPEN_EVT; 94 } 95 else 96 { 97 APPL_TRACE_ERROR ("bta_hf_client_mgmt_cback: PORT_SUCCESS, ignoring handle = %d", port_handle); 98 return; 99 } 100 } 101 /* distinguish server close events */ 102 else if (port_handle == bta_hf_client_cb.scb.conn_handle) 103 { 104 event = BTA_HF_CLIENT_RFC_CLOSE_EVT; 105 } 106 else 107 { 108 event = BTA_HF_CLIENT_RFC_SRV_CLOSE_EVT; 109 } 110 111 if ((p_buf = (tBTA_HF_CLIENT_RFC *) GKI_getbuf(sizeof(tBTA_HF_CLIENT_RFC))) != NULL) 112 { 113 p_buf->hdr.event = event; 114 p_buf->port_handle = port_handle; 115 bta_sys_sendmsg(p_buf); 116 } 117 } 118 119 /******************************************************************************* 120 ** 121 ** Function bta_hf_client_setup_port 122 ** 123 ** Description Setup RFCOMM port for use by HF Client. 124 ** 125 ** 126 ** Returns void 127 ** 128 *******************************************************************************/ 129 void bta_hf_client_setup_port(UINT16 handle) 130 { 131 PORT_SetEventMask(handle, PORT_EV_RXCHAR); 132 PORT_SetEventCallback(handle, bta_hf_client_port_cback); 133 } 134 135 /******************************************************************************* 136 ** 137 ** Function bta_hf_client_start_server 138 ** 139 ** Description Setup RFCOMM server for use by HF Client. 140 ** 141 ** 142 ** Returns void 143 ** 144 *******************************************************************************/ 145 void bta_hf_client_start_server(void) 146 { 147 int port_status; 148 149 if (bta_hf_client_cb.scb.serv_handle > 0) 150 { 151 APPL_TRACE_DEBUG("%s already started, handle: %d", __FUNCTION__, bta_hf_client_cb.scb.serv_handle); 152 return; 153 } 154 155 BTM_SetSecurityLevel(FALSE, "", BTM_SEC_SERVICE_HF_HANDSFREE, bta_hf_client_cb.scb.serv_sec_mask, 156 BT_PSM_RFCOMM, BTM_SEC_PROTO_RFCOMM, bta_hf_client_cb.scn); 157 158 port_status = RFCOMM_CreateConnection(UUID_SERVCLASS_HF_HANDSFREE, bta_hf_client_cb.scn, 159 TRUE, BTA_HF_CLIENT_MTU, (UINT8 *) bd_addr_any, &(bta_hf_client_cb.scb.serv_handle), 160 bta_hf_client_mgmt_cback); 161 162 if (port_status == PORT_SUCCESS) 163 { 164 bta_hf_client_setup_port(bta_hf_client_cb.scb.serv_handle); 165 } 166 else 167 { 168 /* TODO: can we handle this better? */ 169 APPL_TRACE_DEBUG("bta_hf_client_start_server: RFCOMM_CreateConnection returned error:%d", port_status); 170 } 171 172 APPL_TRACE_DEBUG("bta_hf_client_start_server handle: %d", bta_hf_client_cb.scb.serv_handle); 173 } 174 175 /******************************************************************************* 176 ** 177 ** Function bta_hf_client_close_server 178 ** 179 ** Description Close RFCOMM server port for use by HF Client. 180 ** 181 ** 182 ** Returns void 183 ** 184 *******************************************************************************/ 185 void bta_hf_client_close_server(void) 186 { 187 APPL_TRACE_DEBUG("%s %d", __FUNCTION__, bta_hf_client_cb.scb.serv_handle); 188 189 if (bta_hf_client_cb.scb.serv_handle == 0) 190 { 191 APPL_TRACE_DEBUG("%s already stopped", __FUNCTION__); 192 return; 193 } 194 195 RFCOMM_RemoveServer(bta_hf_client_cb.scb.serv_handle); 196 bta_hf_client_cb.scb.serv_handle = 0; 197 } 198 199 /******************************************************************************* 200 ** 201 ** Function bta_hf_client_rfc_do_open 202 ** 203 ** Description Open an RFCOMM connection to the peer device. 204 ** 205 ** 206 ** Returns void 207 ** 208 *******************************************************************************/ 209 void bta_hf_client_rfc_do_open(tBTA_HF_CLIENT_DATA *p_data) 210 { 211 BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_HF_HANDSFREE, 212 bta_hf_client_cb.scb.cli_sec_mask, BT_PSM_RFCOMM, 213 BTM_SEC_PROTO_RFCOMM, bta_hf_client_cb.scb.peer_scn); 214 215 if (RFCOMM_CreateConnection(UUID_SERVCLASS_HF_HANDSFREE, bta_hf_client_cb.scb.peer_scn, 216 FALSE, BTA_HF_CLIENT_MTU, bta_hf_client_cb.scb.peer_addr, &(bta_hf_client_cb.scb.conn_handle), 217 bta_hf_client_mgmt_cback) == PORT_SUCCESS) 218 { 219 bta_hf_client_setup_port(bta_hf_client_cb.scb.conn_handle); 220 APPL_TRACE_DEBUG("bta_hf_client_rfc_do_open : conn_handle = %d", bta_hf_client_cb.scb.conn_handle); 221 } 222 /* RFCOMM create connection failed; send ourselves RFCOMM close event */ 223 else 224 { 225 bta_hf_client_sm_execute(BTA_HF_CLIENT_RFC_CLOSE_EVT, p_data); 226 } 227 } 228 229 /******************************************************************************* 230 ** 231 ** Function bta_hf_client_rfc_do_close 232 ** 233 ** Description Close RFCOMM connection. 234 ** 235 ** 236 ** Returns void 237 ** 238 *******************************************************************************/ 239 void bta_hf_client_rfc_do_close(tBTA_HF_CLIENT_DATA *p_data) 240 { 241 tBTA_HF_CLIENT_RFC *p_buf; 242 UNUSED(p_data); 243 244 if (bta_hf_client_cb.scb.conn_handle) 245 { 246 RFCOMM_RemoveConnection(bta_hf_client_cb.scb.conn_handle); 247 } 248 else 249 { 250 /* Close API was called while HF Client is in Opening state. */ 251 /* Need to trigger the state machine to send callback to the app */ 252 /* and move back to INIT state. */ 253 if ((p_buf = (tBTA_HF_CLIENT_RFC *) GKI_getbuf(sizeof(tBTA_HF_CLIENT_RFC))) != NULL) 254 { 255 p_buf->hdr.event = BTA_HF_CLIENT_RFC_CLOSE_EVT; 256 bta_sys_sendmsg(p_buf); 257 } 258 259 /* Cancel SDP if it had been started. */ 260 if(bta_hf_client_cb.scb.p_disc_db) 261 { 262 (void)SDP_CancelServiceSearch (bta_hf_client_cb.scb.p_disc_db); 263 bta_hf_client_free_db(NULL); 264 } 265 } 266 } 267