static void bta_mce_search_cback(UINT16 result, void * user_data) { tSDP_DISC_REC *p_rec = NULL; tBTA_MCE_MAS_DISCOVERY_COMP evt_data; int found = 0; APPL_TRACE_DEBUG1("bta_mce_start_discovery_cback res: 0x%x", result); bta_mce_cb.sdp_active = BTA_MCE_SDP_ACT_NONE; if (bta_mce_cb.p_dm_cback == NULL) return; evt_data.status = BTA_MCE_FAILURE; bdcpy(evt_data.remote_addr, bta_mce_cb.remote_addr); evt_data.num_mas = 0; if (result == SDP_SUCCESS || result == SDP_DB_FULL) { do { tSDP_DISC_ATTR *p_attr; tSDP_PROTOCOL_ELEM pe; p_rec = SDP_FindServiceUUIDInDb(p_bta_mce_cfg->p_sdp_db, (tBT_UUID*) &bta_mce_mas_uuid, p_rec); APPL_TRACE_DEBUG1("p_rec:%p", p_rec); if (p_rec == NULL) break; if (!SDP_FindProtocolListElemInRec(p_rec, UUID_PROTOCOL_RFCOMM, &pe)) continue; evt_data.mas[found].scn = pe.params[0]; if ((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_SERVICE_NAME)) == NULL) continue; evt_data.mas[found].p_srv_name = (char *) p_attr->attr_value.v.array; evt_data.mas[found].srv_name_len= SDP_DISC_ATTR_LEN(p_attr->attr_len_type); if ((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_MAS_INSTANCE_ID)) == NULL) break; evt_data.mas[found].instance_id = p_attr->attr_value.v.u8; if ((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_SUPPORTED_MSG_TYPE)) == NULL) break; evt_data.mas[found].msg_type = p_attr->attr_value.v.u8; found++; } while (p_rec != NULL && found < BTA_MCE_MAX_MAS_INSTANCES); evt_data.num_mas = found; evt_data.status = BTA_MCE_SUCCESS; } bta_mce_cb.p_dm_cback(BTA_MCE_MAS_DISCOVERY_COMP_EVT, (tBTA_MCE*) &evt_data, user_data); }
/******************************************************************************* ** ** Function bta_ag_sdp_find_attr ** ** Description Process SDP discovery results to find requested attributes ** for requested service. ** ** ** Returns TRUE if results found, FALSE otherwise. ** *******************************************************************************/ BOOLEAN bta_ag_sdp_find_attr(tBTA_AG_SCB *p_scb, tBTA_SERVICE_MASK service) { tSDP_DISC_REC *p_rec = NULL; tSDP_DISC_ATTR *p_attr; tSDP_PROTOCOL_ELEM pe; UINT16 uuid; BOOLEAN result = FALSE; if (service & BTA_HFP_SERVICE_MASK) { uuid = UUID_SERVCLASS_HF_HANDSFREE; p_scb->peer_version = HFP_VERSION_1_1; /* Default version */ } else if (service & BTA_HSP_SERVICE_MASK && p_scb->role == BTA_AG_INT) { uuid = UUID_SERVCLASS_HEADSET_HS; p_scb->peer_version = 0x0100; /* Default version */ } else { return result; } /* loop through all records we found */ while (TRUE) { /* get next record; if none found, we're done */ if ((p_rec = SDP_FindServiceInDb(p_scb->p_disc_db, uuid, p_rec)) == NULL) { if (uuid == UUID_SERVCLASS_HEADSET_HS) { /* Search again in case the peer device is HSP v1.0 */ uuid = UUID_SERVCLASS_HEADSET; if ((p_rec = SDP_FindServiceInDb(p_scb->p_disc_db, uuid, p_rec)) == NULL) { break; } } else break; } /* get scn from proto desc list if initiator */ if (p_scb->role == BTA_AG_INT) { if (SDP_FindProtocolListElemInRec(p_rec, UUID_PROTOCOL_RFCOMM, &pe)) { p_scb->peer_scn = (UINT8) pe.params[0]; } else { continue; } } /* get profile version (if failure, version parameter is not updated) */ SDP_FindProfileVersionInRec(p_rec, uuid, &p_scb->peer_version); /* get features if HFP */ if (service & BTA_HFP_SERVICE_MASK) { if ((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_SUPPORTED_FEATURES)) != NULL) { /* Found attribute. Get value. */ /* There might be race condition between SDP and BRSF. */ /* Do not update if we already received BRSF. */ APPL_TRACE_DEBUG1("bta_ag_sdp_find_attr: peer_attr 0x%x", p_attr->attr_value.v.u16); APPL_TRACE_WARNING0("bta_ag_sdp_find_attr not using value as p_scb->peer_features"); /* Do not use the value as peer_features. ** ** if (p_scb->peer_features == 0) ** p_scb->peer_features = p_attr->attr_value.v.u16; ** ** Reason is, that the service connection negotiation depends on the ** BTA_AG_FEAT_3WAY feature (see the calling of bta_ag_svc_conn_open() ** for BTA_AG_HF_CMD_CMER). A race condition could result in erratic ** behavior. ** ** Background: Using the attr_value for peer_feature was a change introduced ** in android 4.2. That version triggered a number of bug-reports about ** bluetooth being broken. ** ** This problem was observed first hand on a BMW 2005/E46 car kit which does ** not send AT+BRSF and behaves as if it would not support 3WAY. With the newly ** introduced code for using attr_value as peer_feature the result was that ** bluetooth connections to the car kit always terminated after 5 seconds ** (via BTA_AG_SVC_TOUT_EVT). */ } } else /* HSP */ { if ((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_REMOTE_AUDIO_VOLUME_CONTROL)) != NULL) { /* Remote volume control of HSP */ if (p_attr->attr_value.v.u8) p_scb->peer_features |= BTA_AG_PEER_FEAT_VOL; else p_scb->peer_features &= ~BTA_AG_PEER_FEAT_VOL; } } /* found what we needed */ result = TRUE; break; } return result; }
/******************************************************************************* ** ** Function bta_hf_client_sdp_find_attr ** ** Description Process SDP discovery results to find requested attribute ** ** ** Returns TRUE if results found, FALSE otherwise. ** *******************************************************************************/ BOOLEAN bta_hf_client_sdp_find_attr(void) { tSDP_DISC_REC *p_rec = NULL; tSDP_DISC_ATTR *p_attr; tSDP_PROTOCOL_ELEM pe; BOOLEAN result = FALSE; bta_hf_client_cb.scb.peer_version = HFP_VERSION_1_1; /* Default version */ /* loop through all records we found */ while (TRUE) { /* get next record; if none found, we're done */ if ((p_rec = SDP_FindServiceInDb(bta_hf_client_cb.scb.p_disc_db, UUID_SERVCLASS_AG_HANDSFREE, p_rec)) == NULL) { break; } /* get scn from proto desc list if initiator */ if (bta_hf_client_cb.scb.role == BTA_HF_CLIENT_INT) { if (SDP_FindProtocolListElemInRec(p_rec, UUID_PROTOCOL_RFCOMM, &pe)) { bta_hf_client_cb.scb.peer_scn = (UINT8) pe.params[0]; } else { continue; } } /* get profile version (if failure, version parameter is not updated) */ SDP_FindProfileVersionInRec(p_rec, UUID_SERVCLASS_HF_HANDSFREE, &bta_hf_client_cb.scb.peer_version); /* get features */ if ((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_SUPPORTED_FEATURES)) != NULL) { /* Found attribute. Get value. */ /* There might be race condition between SDP and BRSF. */ /* Do not update if we already received BRSF. */ if (bta_hf_client_cb.scb.peer_features == 0) { bta_hf_client_cb.scb.peer_features = p_attr->attr_value.v.u16; /* SDP and BRSF WBS bit are different, correct it if set */ if (bta_hf_client_cb.scb.peer_features & 0x0020) { bta_hf_client_cb.scb.peer_features &= ~0x0020; bta_hf_client_cb.scb.peer_features |= BTA_HF_CLIENT_PEER_CODEC; } /* get network for ability to reject calls */ if ((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_NETWORK)) != NULL) { if (p_attr->attr_value.v.u16 == 0x01) { bta_hf_client_cb.scb.peer_features |= BTA_HF_CLIENT_PEER_REJECT; } } } } /* found what we needed */ result = TRUE; break; } APPL_TRACE_DEBUG("%s peer_version=0x%x peer_features=0x%x", __FUNCTION__, bta_hf_client_cb.scb.peer_version, bta_hf_client_cb.scb.peer_features); return result; }
/******************************************************************************* ** ** Function bta_ag_sdp_find_attr ** ** Description Process SDP discovery results to find requested attributes ** for requested service. ** ** ** Returns TRUE if results found, FALSE otherwise. ** *******************************************************************************/ BOOLEAN bta_ag_sdp_find_attr(tBTA_AG_SCB *p_scb, tBTA_SERVICE_MASK service) { tSDP_DISC_REC *p_rec = NULL; tSDP_DISC_ATTR *p_attr; tSDP_PROTOCOL_ELEM pe; UINT16 uuid; BOOLEAN result = FALSE; if (service & BTA_HFP_SERVICE_MASK) { uuid = UUID_SERVCLASS_HF_HANDSFREE; p_scb->peer_version = HFP_VERSION_1_1; /* Default version */ } else if (service & BTA_HSP_SERVICE_MASK && p_scb->role == BTA_AG_INT) { uuid = UUID_SERVCLASS_HEADSET_HS; p_scb->peer_version = 0x0100; /* Default version */ } else { return result; } /* loop through all records we found */ while (TRUE) { /* get next record; if none found, we're done */ if ((p_rec = SDP_FindServiceInDb(p_scb->p_disc_db, uuid, p_rec)) == NULL) { if (uuid == UUID_SERVCLASS_HEADSET_HS) { /* Search again in case the peer device is HSP v1.0 */ uuid = UUID_SERVCLASS_HEADSET; if ((p_rec = SDP_FindServiceInDb(p_scb->p_disc_db, uuid, p_rec)) == NULL) { break; } } else break; } /* get scn from proto desc list if initiator */ if (p_scb->role == BTA_AG_INT) { if (SDP_FindProtocolListElemInRec(p_rec, UUID_PROTOCOL_RFCOMM, &pe)) { p_scb->peer_scn = (UINT8) pe.params[0]; } else { continue; } } /* get profile version (if failure, version parameter is not updated) */ SDP_FindProfileVersionInRec(p_rec, uuid, &p_scb->peer_version); /* get features if HFP */ if (service & BTA_HFP_SERVICE_MASK) { if ((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_SUPPORTED_FEATURES)) != NULL) { /* Found attribute. Get value. */ /* There might be race condition between SDP and BRSF. */ /* Do not update if we already received BRSF. */ if (p_scb->peer_features == 0) p_scb->peer_features = p_attr->attr_value.v.u16; } } else /* HSP */ { if ((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_REMOTE_AUDIO_VOLUME_CONTROL)) != NULL) { /* Remote volume control of HSP */ if (p_attr->attr_value.v.u8) p_scb->peer_features |= BTA_AG_PEER_FEAT_VOL; else p_scb->peer_features &= ~BTA_AG_PEER_FEAT_VOL; } } /* found what we needed */ result = TRUE; break; } return result; }