/******************************************************************************* ** ** Function bta_ag_api_result ** ** Description Handle an API result event. ** ** ** Returns void ** *******************************************************************************/ static void bta_ag_api_result(tBTA_AG_DATA *p_data) { tBTA_AG_SCB *p_scb; int i; if (p_data->hdr.layer_specific != BTA_AG_HANDLE_ALL) { if ((p_scb = bta_ag_scb_by_idx(p_data->hdr.layer_specific)) != NULL) { APPL_TRACE_DEBUG("bta_ag_api_result: p_scb 0x%08x ", p_scb); bta_ag_sm_execute(p_scb, BTA_AG_API_RESULT_EVT, p_data); } } else { for (i = 0, p_scb = &bta_ag_cb.scb[0]; i < BTA_AG_NUM_SCB; i++, p_scb++) { if (p_scb->in_use && p_scb->svc_conn) { APPL_TRACE_DEBUG("bta_ag_api_result p_scb 0x%08x ", p_scb); bta_ag_sm_execute(p_scb, BTA_AG_API_RESULT_EVT, p_data); } } } }
/******************************************************************************* ** ** Function bta_ag_disc_int_res ** ** Description This function handles a discovery result when initiator. ** ** ** Returns void ** *******************************************************************************/ void bta_ag_disc_int_res(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) { UINT16 event = BTA_AG_DISC_FAIL_EVT; APPL_TRACE_DEBUG ("bta_ag_disc_int_res: Status: %d", p_data->disc_result.status); /* if found service */ if (p_data->disc_result.status == SDP_SUCCESS || p_data->disc_result.status == SDP_DB_FULL) { /* get attributes */ if (bta_ag_sdp_find_attr(p_scb, p_scb->open_services)) { /* set connected service */ p_scb->conn_service = bta_ag_service_to_idx(p_scb->open_services); /* send ourselves sdp ok event */ event = BTA_AG_DISC_OK_EVT; } } /* free discovery db */ bta_ag_free_db(p_scb, p_data); /* if service not found check if we should search for other service */ if ((event == BTA_AG_DISC_FAIL_EVT) && (p_data->disc_result.status == SDP_SUCCESS || p_data->disc_result.status == SDP_DB_FULL || p_data->disc_result.status == SDP_NO_RECS_MATCH)) { if ((p_scb->open_services & BTA_HFP_SERVICE_MASK) && (p_scb->open_services & BTA_HSP_SERVICE_MASK)) { /* search for HSP */ p_scb->open_services &= ~BTA_HFP_SERVICE_MASK; bta_ag_do_disc(p_scb, p_scb->open_services); } else if ((p_scb->open_services & BTA_HSP_SERVICE_MASK) && (p_scb->hsp_version == HSP_VERSION_1_2)) { /* search for UUID_SERVCLASS_HEADSET for HSP 1.0 device */ p_scb->hsp_version = HSP_VERSION_1_0; bta_ag_do_disc(p_scb, p_scb->open_services); } else { /* send ourselves sdp ok/fail event */ bta_ag_sm_execute(p_scb, event, p_data); } } else { /* send ourselves sdp ok/fail event */ bta_ag_sm_execute(p_scb, event, p_data); } }
/******************************************************************************* ** ** Function bta_ag_api_disable ** ** Description Handle an API disable event. ** ** ** Returns void ** *******************************************************************************/ static void bta_ag_api_disable(tBTA_AG_DATA *p_data) { /* deregister all scbs in use */ tBTA_AG_SCB *p_scb = &bta_ag_cb.scb[0]; BOOLEAN do_dereg = FALSE; int i; if (!bta_sys_is_register (BTA_ID_AG)) { APPL_TRACE_ERROR("BTA AG is already disabled, ignoring ..."); return; } /* De-register with BTA system manager */ bta_sys_deregister(BTA_ID_AG); for (i = 0; i < BTA_AG_NUM_SCB; i++, p_scb++) { if (p_scb->in_use) { bta_ag_sm_execute(p_scb, BTA_AG_API_DEREGISTER_EVT, p_data); do_dereg = TRUE; } } if (!do_dereg) { /* Done, send callback evt to app */ (*bta_ag_cb.p_cback)(BTA_AG_DISABLE_EVT, NULL); } bta_sys_collision_register (BTA_ID_AG, NULL); }
/******************************************************************************* ** ** Function bta_ag_api_result ** ** Description Handle an API result event. ** ** ** Returns void ** *******************************************************************************/ static void bta_ag_api_result(tBTA_AG_DATA *p_data) { tBTA_AG_SCB *p_scb; int i; if (p_data->hdr.layer_specific != BTA_AG_HANDLE_ALL) { if ((p_scb = bta_ag_scb_by_idx(p_data->hdr.layer_specific)) != NULL) { bta_ag_sm_execute(p_scb, BTA_AG_API_RESULT_EVT, p_data); } } else { for (i = 0, p_scb = &bta_ag_cb.scb[0]; i < BTA_AG_NUM_SCB; i++, p_scb++) { if (p_scb->in_use) { bta_ag_sm_execute(p_scb, BTA_AG_API_RESULT_EVT, p_data); } } } }
/******************************************************************************* ** ** Function bta_ag_api_register ** ** Description Handle an API event registers a new service. ** ** ** Returns void ** *******************************************************************************/ static void bta_ag_api_register(tBTA_AG_DATA *p_data) { tBTA_AG_SCB *p_scb; tBTA_AG_REGISTER reg; /* allocate an scb */ if ((p_scb = bta_ag_scb_alloc()) != NULL) { bta_ag_sm_execute(p_scb, p_data->hdr.event, p_data); } else { reg.status = BTA_AG_FAIL_RESOURCES; (*bta_ag_cb.p_cback)(BTA_AG_REGISTER_EVT, (tBTA_AG *) ®); } }
/******************************************************************************* ** ** Function bta_ag_rfc_do_open ** ** Description Open an RFCOMM connection to the peer device. ** ** ** Returns void ** *******************************************************************************/ void bta_ag_rfc_do_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) { BTM_SetSecurityLevel(TRUE, "", bta_ag_sec_id[p_scb->conn_service], p_scb->cli_sec_mask, BT_PSM_RFCOMM, BTM_SEC_PROTO_RFCOMM, p_scb->peer_scn); if (RFCOMM_CreateConnection(bta_ag_uuid[p_scb->conn_service], p_scb->peer_scn, FALSE, BTA_AG_MTU, p_scb->peer_addr, &(p_scb->conn_handle), bta_ag_mgmt_cback_tbl[bta_ag_scb_to_idx(p_scb) - 1]) == PORT_SUCCESS) { bta_ag_setup_port(p_scb, p_scb->conn_handle); APPL_TRACE_DEBUG("bta_ag_rfc_do_open : conn_handle = %d", p_scb->conn_handle); } /* RFCOMM create connection failed; send ourselves RFCOMM close event */ else { bta_ag_sm_execute(p_scb, BTA_AG_RFC_CLOSE_EVT, p_data); } }
/******************************************************************************* ** ** Function bta_ag_hdl_event ** ** Description Data gateway main event handling function. ** ** ** Returns BOOLEAN ** *******************************************************************************/ BOOLEAN bta_ag_hdl_event(BT_HDR *p_msg) { tBTA_AG_SCB *p_scb; APPL_TRACE_DEBUG("bta_ag_hdl_event: Event 0x%04x ", p_msg->event); switch (p_msg->event) { /* handle enable event */ case BTA_AG_API_ENABLE_EVT: bta_ag_api_enable((tBTA_AG_DATA *) p_msg); break; /* handle disable event */ case BTA_AG_API_DISABLE_EVT: bta_ag_api_disable((tBTA_AG_DATA *) p_msg); break; /* handle register event */ case BTA_AG_API_REGISTER_EVT: bta_ag_api_register((tBTA_AG_DATA *) p_msg); break; /* handle result event */ case BTA_AG_API_RESULT_EVT: bta_ag_api_result((tBTA_AG_DATA *) p_msg); break; /* all others reference scb by handle */ default: if ((p_scb = bta_ag_scb_by_idx(p_msg->layer_specific)) != NULL) { APPL_TRACE_DEBUG("bta_ag_hdl_event: p_scb 0x%08x ", p_scb); bta_ag_sm_execute(p_scb, p_msg->event, (tBTA_AG_DATA *) p_msg); } break; } return TRUE; }
/******************************************************************************* ** ** Function bta_ag_do_disc ** ** Description Do service discovery. ** ** ** Returns void ** *******************************************************************************/ void bta_ag_do_disc(tBTA_AG_SCB *p_scb, tBTA_SERVICE_MASK service) { tSDP_UUID uuid_list[2]; UINT16 num_uuid = 1; UINT16 attr_list[4]; UINT8 num_attr; BOOLEAN db_inited = FALSE; /* HFP initiator; get proto list and features */ if (service & BTA_HFP_SERVICE_MASK && p_scb->role == BTA_AG_INT) { attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST; attr_list[1] = ATTR_ID_PROTOCOL_DESC_LIST; attr_list[2] = ATTR_ID_BT_PROFILE_DESC_LIST; attr_list[3] = ATTR_ID_SUPPORTED_FEATURES; num_attr = 4; uuid_list[0].uu.uuid16 = UUID_SERVCLASS_HF_HANDSFREE; } /* HFP acceptor; get features */ else if (service & BTA_HFP_SERVICE_MASK && p_scb->role == BTA_AG_ACP) { attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST; attr_list[1] = ATTR_ID_BT_PROFILE_DESC_LIST; attr_list[2] = ATTR_ID_SUPPORTED_FEATURES; num_attr = 3; uuid_list[0].uu.uuid16 = UUID_SERVCLASS_HF_HANDSFREE; } /* HSP initiator; get proto list */ else if (service & BTA_HSP_SERVICE_MASK && p_scb->role == BTA_AG_INT) { attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST; attr_list[1] = ATTR_ID_PROTOCOL_DESC_LIST; attr_list[2] = ATTR_ID_BT_PROFILE_DESC_LIST; attr_list[3] = ATTR_ID_REMOTE_AUDIO_VOLUME_CONTROL; num_attr = 4; uuid_list[0].uu.uuid16 = UUID_SERVCLASS_HEADSET; /* Legacy from HSP v1.0 */ if (p_scb->hsp_version >= HSP_VERSION_1_2) { uuid_list[1].uu.uuid16 = UUID_SERVCLASS_HEADSET_HS; num_uuid = 2; } } /* HSP acceptor; no discovery */ else { return; } /* allocate buffer for sdp database */ p_scb->p_disc_db = (tSDP_DISCOVERY_DB *) GKI_getbuf(BTA_AG_DISC_BUF_SIZE); if(p_scb->p_disc_db) { /* set up service discovery database; attr happens to be attr_list len */ uuid_list[0].len = LEN_UUID_16; uuid_list[1].len = LEN_UUID_16; db_inited = SDP_InitDiscoveryDb(p_scb->p_disc_db, BTA_AG_DISC_BUF_SIZE, num_uuid, uuid_list, num_attr, attr_list); } if(db_inited) { /*Service discovery not initiated */ db_inited = SDP_ServiceSearchAttributeRequest(p_scb->peer_addr, p_scb->p_disc_db, bta_ag_sdp_cback_tbl[bta_ag_scb_to_idx(p_scb) - 1]); } if(!db_inited) { /*free discover db */ bta_ag_free_db(p_scb, NULL); /* sent failed event */ bta_ag_sm_execute(p_scb, BTA_AG_DISC_FAIL_EVT, NULL); } }