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 "bd.h" 32 #include "bt_utils.h" 33 34 /******************************************************************************* 35 ** 36 ** Function bta_hf_client_port_cback 37 ** 38 ** Description RFCOMM Port callback 39 ** 40 ** 41 ** Returns void 42 ** 43 *******************************************************************************/ 44 static void bta_hf_client_port_cback(UINT32 code, UINT16 port_handle) 45 { 46 BT_HDR *p_buf; 47 UNUSED(code); 48 49 /* ignore port events for port handles other than connected handle */ 50 if (port_handle != bta_hf_client_cb.scb.conn_handle) 51 { 52 APPL_TRACE_DEBUG("bta_hf_client_port_cback ignoring handle:%d conn_handle = %d", 53 port_handle, bta_hf_client_cb.scb.conn_handle); 54 return; 55 } 56 57 if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL) 58 { 59 p_buf->event = BTA_HF_CLIENT_RFC_DATA_EVT; 60 bta_sys_sendmsg(p_buf); 61 } 62 } 63 64 /******************************************************************************* 65 ** 66 ** Function bta_hf_client_mgmt_cback 67 ** 68 ** Description RFCOMM management callback 69 ** 70 ** 71 ** Returns void 72 ** 73 *******************************************************************************/ 74 static void bta_hf_client_mgmt_cback(UINT32 code, UINT16 port_handle) 75 { 76 tBTA_HF_CLIENT_RFC *p_buf; 77 UINT16 event; 78 79 APPL_TRACE_DEBUG("bta_hf_client_mgmt_cback : code = %d, port_handle = %d, conn_handle = %d, serv_handle = %d", 80 code, port_handle, bta_hf_client_cb.scb.conn_handle, bta_hf_client_cb.scb.serv_handle); 81 82 /* ignore close event for port handles other than connected handle */ 83 if ((code != PORT_SUCCESS) && (port_handle != bta_hf_client_cb.scb.conn_handle)) 84 { 85 APPL_TRACE_DEBUG("bta_hf_client_mgmt_cback ignoring handle:%d", port_handle); 86 return; 87 } 88 89 if (code == PORT_SUCCESS) 90 { 91 if ((bta_hf_client_cb.scb.conn_handle && (port_handle == bta_hf_client_cb.scb.conn_handle)) || /* outgoing connection */ 92 (port_handle == bta_hf_client_cb.scb.serv_handle)) /* incoming connection */ 93 { 94 event = BTA_HF_CLIENT_RFC_OPEN_EVT; 95 } 96 else 97 { 98 APPL_TRACE_ERROR ("bta_hf_client_mgmt_cback: PORT_SUCCESS, ignoring handle = %d", port_handle); 99 return; 100 } 101 } 102 /* distinguish server close events */ 103 else if (port_handle == bta_hf_client_cb.scb.conn_handle) 104 { 105 event = BTA_HF_CLIENT_RFC_CLOSE_EVT; 106 } 107 else 108 { 109 event = BTA_HF_CLIENT_RFC_SRV_CLOSE_EVT; 110 } 111 112 if ((p_buf = (tBTA_HF_CLIENT_RFC *) GKI_getbuf(sizeof(tBTA_HF_CLIENT_RFC))) != NULL) 113 { 114 p_buf->hdr.event = event; 115 p_buf->port_handle = port_handle; 116 bta_sys_sendmsg(p_buf); 117 } 118 } 119 120 /******************************************************************************* 121 ** 122 ** Function bta_hf_client_setup_port 123 ** 124 ** Description Setup RFCOMM port for use by HF Client. 125 ** 126 ** 127 ** Returns void 128 ** 129 *******************************************************************************/ 130 void bta_hf_client_setup_port(UINT16 handle) 131 { 132 PORT_SetEventMask(handle, PORT_EV_RXCHAR); 133 PORT_SetEventCallback(handle, bta_hf_client_port_cback); 134 } 135 136 /******************************************************************************* 137 ** 138 ** Function bta_hf_client_start_server 139 ** 140 ** Description Setup RFCOMM server for use by HF Client. 141 ** 142 ** 143 ** Returns void 144 ** 145 *******************************************************************************/ 146 void bta_hf_client_start_server(void) 147 { 148 int i; 149 int port_status; 150 151 if (bta_hf_client_cb.scb.serv_handle > 0) 152 { 153 APPL_TRACE_DEBUG("%s already started, handle: %d", __FUNCTION__, bta_hf_client_cb.scb.serv_handle); 154 return; 155 } 156 157 BTM_SetSecurityLevel(FALSE, "", BTM_SEC_SERVICE_HF_HANDSFREE, bta_hf_client_cb.scb.serv_sec_mask, 158 BT_PSM_RFCOMM, BTM_SEC_PROTO_RFCOMM, bta_hf_client_cb.scn); 159 160 port_status = RFCOMM_CreateConnection(UUID_SERVCLASS_HF_HANDSFREE, bta_hf_client_cb.scn, 161 TRUE, BTA_HF_CLIENT_MTU, (UINT8 *) bd_addr_any, &(bta_hf_client_cb.scb.serv_handle), 162 bta_hf_client_mgmt_cback); 163 164 if (port_status == PORT_SUCCESS) 165 { 166 bta_hf_client_setup_port(bta_hf_client_cb.scb.serv_handle); 167 } 168 else 169 { 170 /* TODO: can we handle this better? */ 171 APPL_TRACE_DEBUG("bta_hf_client_start_server: RFCOMM_CreateConnection returned error:%d", port_status); 172 } 173 174 APPL_TRACE_DEBUG("bta_hf_client_start_server handle: %d", bta_hf_client_cb.scb.serv_handle); 175 } 176 177 /******************************************************************************* 178 ** 179 ** Function bta_hf_client_close_server 180 ** 181 ** Description Close RFCOMM server port for use by HF Client. 182 ** 183 ** 184 ** Returns void 185 ** 186 *******************************************************************************/ 187 void bta_hf_client_close_server(void) 188 { 189 APPL_TRACE_DEBUG("%s %d", __FUNCTION__, bta_hf_client_cb.scb.serv_handle); 190 191 if (bta_hf_client_cb.scb.serv_handle == 0) 192 { 193 APPL_TRACE_DEBUG("%s already stopped", __FUNCTION__); 194 return; 195 } 196 197 RFCOMM_RemoveServer(bta_hf_client_cb.scb.serv_handle); 198 bta_hf_client_cb.scb.serv_handle = 0; 199 } 200 201 /******************************************************************************* 202 ** 203 ** Function bta_hf_client_rfc_do_open 204 ** 205 ** Description Open an RFCOMM connection to the peer device. 206 ** 207 ** 208 ** Returns void 209 ** 210 *******************************************************************************/ 211 void bta_hf_client_rfc_do_open(tBTA_HF_CLIENT_DATA *p_data) 212 { 213 BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_HF_HANDSFREE, 214 bta_hf_client_cb.scb.cli_sec_mask, BT_PSM_RFCOMM, 215 BTM_SEC_PROTO_RFCOMM, bta_hf_client_cb.scb.peer_scn); 216 217 if (RFCOMM_CreateConnection(UUID_SERVCLASS_HF_HANDSFREE, bta_hf_client_cb.scb.peer_scn, 218 FALSE, BTA_HF_CLIENT_MTU, bta_hf_client_cb.scb.peer_addr, &(bta_hf_client_cb.scb.conn_handle), 219 bta_hf_client_mgmt_cback) == PORT_SUCCESS) 220 { 221 bta_hf_client_setup_port(bta_hf_client_cb.scb.conn_handle); 222 APPL_TRACE_DEBUG("bta_hf_client_rfc_do_open : conn_handle = %d", bta_hf_client_cb.scb.conn_handle); 223 } 224 /* RFCOMM create connection failed; send ourselves RFCOMM close event */ 225 else 226 { 227 bta_hf_client_sm_execute(BTA_HF_CLIENT_RFC_CLOSE_EVT, p_data); 228 } 229 } 230 231 /******************************************************************************* 232 ** 233 ** Function bta_hf_client_rfc_do_close 234 ** 235 ** Description Close RFCOMM connection. 236 ** 237 ** 238 ** Returns void 239 ** 240 *******************************************************************************/ 241 void bta_hf_client_rfc_do_close(tBTA_HF_CLIENT_DATA *p_data) 242 { 243 tBTA_HF_CLIENT_RFC *p_buf; 244 UNUSED(p_data); 245 246 if (bta_hf_client_cb.scb.conn_handle) 247 { 248 RFCOMM_RemoveConnection(bta_hf_client_cb.scb.conn_handle); 249 } 250 else 251 { 252 /* Close API was called while HF Client is in Opening state. */ 253 /* Need to trigger the state machine to send callback to the app */ 254 /* and move back to INIT state. */ 255 if ((p_buf = (tBTA_HF_CLIENT_RFC *) GKI_getbuf(sizeof(tBTA_HF_CLIENT_RFC))) != NULL) 256 { 257 p_buf->hdr.event = BTA_HF_CLIENT_RFC_CLOSE_EVT; 258 bta_sys_sendmsg(p_buf); 259 } 260 261 /* Cancel SDP if it had been started. */ 262 if(bta_hf_client_cb.scb.p_disc_db) 263 { 264 (void)SDP_CancelServiceSearch (bta_hf_client_cb.scb.p_disc_db); 265 bta_hf_client_free_db(NULL); 266 } 267 } 268 } 269