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