static void *rfcomm_cback(tBTA_JV_EVT event, tBTA_JV *p_data, void *user_data) { int rc; void* new_user_data = NULL; APPL_TRACE_DEBUG1("event=%s", jv_evt[event]); switch (event) { case BTA_JV_RFCOMM_START_EVT: on_srv_rfc_listen_started(&p_data->rfc_start, (uint32_t)user_data); break; case BTA_JV_RFCOMM_CL_INIT_EVT: on_cl_rfc_init(&p_data->rfc_cl_init, (uint32_t)user_data); break; case BTA_JV_RFCOMM_OPEN_EVT: BTA_JvSetPmProfile(p_data->rfc_open.handle,BTA_JV_PM_ID_1,BTA_JV_CONN_OPEN); on_cli_rfc_connect(&p_data->rfc_open, (uint32_t)user_data); break; case BTA_JV_RFCOMM_SRV_OPEN_EVT: BTA_JvSetPmProfile(p_data->rfc_srv_open.handle,BTA_JV_PM_ALL,BTA_JV_CONN_OPEN); new_user_data = (void*)on_srv_rfc_connect(&p_data->rfc_srv_open, (uint32_t)user_data); break; case BTA_JV_RFCOMM_CLOSE_EVT: APPL_TRACE_DEBUG1("BTA_JV_RFCOMM_CLOSE_EVT: user_data:%d", (uint32_t)user_data); on_rfc_close(&p_data->rfc_close, (uint32_t)user_data); break; case BTA_JV_RFCOMM_READ_EVT: APPL_TRACE_DEBUG0("BTA_JV_RFCOMM_READ_EVT not used"); break; case BTA_JV_RFCOMM_WRITE_EVT: on_rfc_write_done(&p_data->rfc_write, (uint32_t)user_data); break; case BTA_JV_RFCOMM_DATA_IND_EVT: APPL_TRACE_DEBUG0("BTA_JV_RFCOMM_DATA_IND_EVT not used"); break; case BTA_JV_RFCOMM_CONG_EVT: //on_rfc_cong(&p_data->rfc_cong); on_rfc_outgoing_congest(&p_data->rfc_cong, (uint32_t)user_data); break; default: APPL_TRACE_ERROR2("unhandled event %d, slot id:%d", event, (uint32_t)user_data); break; } return new_user_data; }
int btsock_thread_add_fd(int h, int fd, int type, int flags, uint32_t user_id) { if(h < 0 || h >= MAX_THREAD) { APPL_TRACE_ERROR1("invalid bt thread handle:%d", h); return FALSE; } if(ts[h].cmd_fdw == -1) { APPL_TRACE_ERROR0("cmd socket is not created. socket thread may not initialized"); return FALSE; } if(flags & SOCK_THREAD_ADD_FD_SYNC) { //must executed in socket poll thread if(ts[h].thread_id == pthread_self()) { //cleanup one-time flags flags &= ~SOCK_THREAD_ADD_FD_SYNC; add_poll(h, fd, type, flags, user_id); return TRUE; } APPL_TRACE_DEBUG0("THREAD_ADD_FD_SYNC is not called in poll thread, fallback to async"); } sock_cmd_t cmd = {CMD_ADD_FD, fd, type, flags, user_id}; APPL_TRACE_DEBUG2("adding fd:%d, flags:0x%x", fd, flags); return send(ts[h].cmd_fdw, &cmd, sizeof(cmd), 0) == sizeof(cmd); }
void bta_hf_client_send_at_bia(void) { char buf[BTA_HF_CLIENT_AT_MAX_LEN]; int at_len; int i; APPL_TRACE_DEBUG1("%s", __FUNCTION__); if (bta_hf_client_cb.scb.peer_version < HFP_VERSION_1_6) { APPL_TRACE_DEBUG0("Remote does not Support AT+BIA"); return; } at_len = snprintf(buf, sizeof(buf), "AT+BIA="); for(i = 0; i < BTA_HF_CLIENT_AT_INDICATOR_COUNT; i++) { int sup = bta_hf_client_cb.scb.at_cb.indicator_lookup[i] == -1 ? 0 : 1; at_len += snprintf(buf + at_len, sizeof(buf) - at_len, "%u,", sup); } buf[at_len - 1] = '\r'; if (at_len < 0) { APPL_TRACE_ERROR0("HFPClient: AT command Framing error"); return; } bta_hf_client_send_at(BTA_HF_CLIENT_AT_BIA, buf, at_len); }
/******************************************************************************* ** ** Function bta_av_co_audio_start ** ** Description This function is called by AV when the audio streaming data ** transfer is started. ** ** ** Returns void ** *******************************************************************************/ BTA_API void bta_av_co_audio_start(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type, UINT8 *p_codec_info, BOOLEAN *p_no_rtp_hdr) { FUNC_TRACE(); APPL_TRACE_DEBUG0("bta_av_co_audio_start"); }
/******************************************************************************* ** ** Function bta_hl_find_sink_or_src_srv_class_in_db ** ** Description This function queries an SDP database for either a HDP Sink or ** Source service class ID. ** If the p_start_rec pointer is NULL, it looks from the beginning ** of the database, else it continues from the next record after ** p_start_rec. ** ** Returns Pointer to record containing service class, or NULL ** *******************************************************************************/ tSDP_DISC_REC *bta_hl_find_sink_or_src_srv_class_in_db (const tSDP_DISCOVERY_DB *p_db, const tSDP_DISC_REC *p_start_rec) { #if SDP_CLIENT_ENABLED == TRUE tSDP_DISC_REC *p_rec; tSDP_DISC_ATTR *p_attr, *p_sattr; /* Must have a valid database */ if (p_db == NULL) return(NULL); if (!p_start_rec) { p_rec = p_db->p_first_rec; } else { p_rec = p_start_rec->p_next_rec; } while (p_rec) { p_attr = p_rec->p_first_attr; while (p_attr) { if ((p_attr->attr_id == ATTR_ID_SERVICE_CLASS_ID_LIST) && (SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) == DATA_ELE_SEQ_DESC_TYPE)) { for (p_sattr = p_attr->attr_value.v.p_sub_attr; p_sattr; p_sattr = p_sattr->p_next_attr) { if ((SDP_DISC_ATTR_TYPE(p_sattr->attr_len_type) == UUID_DESC_TYPE) && (SDP_DISC_ATTR_LEN(p_sattr->attr_len_type) == 2) && ( (p_sattr->attr_value.v.u16 == UUID_SERVCLASS_HDP_SINK) || (p_sattr->attr_value.v.u16 == UUID_SERVCLASS_HDP_SOURCE)) ) { return(p_rec); } } break; } p_attr = p_attr->p_next_attr; } p_rec = p_rec->p_next_rec; } #endif /* If here, no matching UUID found */ #if BTA_HL_DEBUG == TRUE APPL_TRACE_DEBUG0("bta_hl_find_sink_or_src_srv_class_in_db failed"); #endif return(NULL); }
static inline rfc_slot_t* find_rfc_slot_requesting_sdp() { int i; for(i = 0; i < MAX_RFC_CHANNEL; i++) { if(rfc_slots[i].id && rfc_slots[i].f.doing_sdp_request) return &rfc_slots[i]; } APPL_TRACE_DEBUG0("can not find any slot is requesting sdp"); return NULL; }
/******************************************************************************* ** ** Function bta_av_co_audio_sink_supports_cp ** ** Description Check if a sink supports the current content protection ** ** Returns TRUE if the sink supports this CP, FALSE otherwise ** *******************************************************************************/ static BOOLEAN bta_av_co_audio_sink_supports_cp(const tBTA_AV_CO_SINK *p_sink) { FUNC_TRACE(); /* Check if content protection is enabled for this stream */ if (bta_av_co_cp_get_flag() != BTA_AV_CP_SCMS_COPY_FREE) { return bta_av_co_audio_sink_has_scmst(p_sink); } else { APPL_TRACE_DEBUG0("bta_av_co_audio_sink_supports_cp: not required"); return TRUE; } }
void bta_hf_client_send_at_cnum(void) { char *buf; APPL_TRACE_DEBUG1("%s", __FUNCTION__); if (!service_availability) { APPL_TRACE_DEBUG0("Skip AT+CNUM no Service"); return; } buf = "AT+CNUM\r"; bta_hf_client_send_at(BTA_HF_CLIENT_AT_CNUM, buf, strlen(buf)); }
/******************************************************************************* ** ** Function bta_av_hdl_event ** ** Description Advanced audio/video main event handling function. ** ** ** Returns BOOLEAN ** *******************************************************************************/ BOOLEAN bta_av_hdl_event(BT_HDR *p_msg) { UINT16 event = p_msg->event; UINT16 first_event = BTA_AV_FIRST_NSM_EVT; if (event > BTA_AV_LAST_EVT) { return TRUE; /* to free p_msg */ } if(event >= first_event) { #if (defined(BTA_AV_DEBUG) && BTA_AV_DEBUG == TRUE) APPL_TRACE_VERBOSE2("AV nsm event=0x%x(%s)", event, bta_av_evt_code(event)); #else APPL_TRACE_VERBOSE1("AV nsm event=0x%x", event); #endif /* non state machine events */ (*bta_av_nsm_act[event - BTA_AV_FIRST_NSM_EVT]) ((tBTA_AV_DATA *) p_msg); #ifdef A2DP_SINK if (event == BTA_AV_CI_SNK_DATA_READY_EVT) { APPL_TRACE_DEBUG0("not to free p_msg, media task uses it directly to avoid memory copy"); return FALSE; } #endif } else if (event >= BTA_AV_FIRST_SM_EVT && event <= BTA_AV_LAST_SM_EVT) { #if (defined(BTA_AV_DEBUG) && BTA_AV_DEBUG == TRUE) APPL_TRACE_VERBOSE2("AV sm event=0x%x(%s)", event, bta_av_evt_code(event)); #else APPL_TRACE_VERBOSE1("AV sm event=0x%x", event); #endif /* state machine events */ bta_av_sm_execute(&bta_av_cb, p_msg->event, (tBTA_AV_DATA *) p_msg); } else { APPL_TRACE_VERBOSE1("handle=0x%x", p_msg->layer_specific); /* stream state machine events */ bta_av_ssm_execute( bta_av_hndl_to_scb(p_msg->layer_specific), p_msg->event, (tBTA_AV_DATA *) p_msg); } return TRUE; }
/******************************************************************************* ** ** Function bta_ag_get_other_idle_scb ** ** Description Return other scb if it is in INIT st. ** ** ** Returns Pointer to other scb if INIT st, NULL otherwise. ** *******************************************************************************/ tBTA_AG_SCB *bta_ag_get_other_idle_scb (tBTA_AG_SCB *p_curr_scb) { tBTA_AG_SCB *p_scb = &bta_ag_cb.scb[0]; UINT8 xx; for (xx = 0; xx < BTA_AG_NUM_SCB; xx++, p_scb++) { if (p_scb->in_use && (p_scb != p_curr_scb) && (p_scb->state == BTA_AG_INIT_ST)) { return p_scb; } } /* no other scb found */ APPL_TRACE_DEBUG0("bta_ag_get_other_idle_scb: No idle AG scb"); return NULL; }
/******************************************************************************* ** ** Function bta_ag_other_scb_open ** ** Description Check whether any other scb is in open state. ** ** ** Returns TRUE if another scb is in open state, FALSE otherwise. ** *******************************************************************************/ BOOLEAN bta_ag_other_scb_open(tBTA_AG_SCB *p_curr_scb) { tBTA_AG_SCB *p_scb = &bta_ag_cb.scb[0]; int i; for (i = 0; i < BTA_AG_NUM_SCB; i++, p_scb++) { if (p_scb->in_use && p_scb != p_curr_scb && p_scb->state == BTA_AG_OPEN_ST) { return TRUE; } } /* no other scb found */ APPL_TRACE_DEBUG0("No other ag scb open"); return FALSE; }
void bta_hf_client_send_at_cops(BOOLEAN query) { char *buf; APPL_TRACE_DEBUG1("%s", __FUNCTION__); if (!service_availability) { APPL_TRACE_DEBUG0("Skip AT+COPS no service"); return; } if (query) buf = "AT+COPS?\r"; else buf = "AT+COPS=3,0\r"; bta_hf_client_send_at(BTA_HF_CLIENT_AT_COPS, buf, strlen(buf)); }
/******************************************************************************* ** ** Function bta_av_co_cp_is_scmst ** ** Description Check if a content protection service is SCMS-T ** ** Returns TRUE if this CP is SCMS-T, FALSE otherwise ** *******************************************************************************/ static BOOLEAN bta_av_co_cp_is_scmst(const UINT8 *p_protectinfo) { UINT16 cp_id; FUNC_TRACE(); if (*p_protectinfo >= BTA_AV_CP_LOSC) { p_protectinfo++; STREAM_TO_UINT16(cp_id, p_protectinfo); if (cp_id == BTA_AV_CP_SCMS_T_ID) { APPL_TRACE_DEBUG0("bta_av_co_cp_is_scmst: SCMS-T found"); return TRUE; } } return FALSE; }
/******************************************************************************* ** ** Function bta_ag_colli_timer_cback ** ** Description AG connection collision timer callback ** ** ** Returns void ** *******************************************************************************/ static void bta_ag_colli_timer_cback (TIMER_LIST_ENT *p_tle) { tBTA_AG_SCB *p_scb; APPL_TRACE_DEBUG0 ("bta_ag_colli_timer_cback"); if (p_tle) { p_scb = (tBTA_AG_SCB *)p_tle->param; if (p_scb) { p_scb->colli_tmr_on = FALSE; /* If the peer haven't opened AG connection */ /* we will restart opening process. */ bta_ag_resume_open (p_scb); } } }
/******************************************************************************* ** ** Function bta_mce_get_remote_mas_instances ** ** Description Discovers MAS instances on remote device ** ** Returns void ** *******************************************************************************/ void bta_mce_get_remote_mas_instances(tBTA_MCE_MSG *p_data) { if(p_data == NULL) { APPL_TRACE_DEBUG0("MCE control block handle is null"); return; } tBTA_MCE_STATUS status = BTA_MCE_FAILURE; APPL_TRACE_DEBUG2("%s in, sdp_active:%d", __FUNCTION__, bta_mce_cb.sdp_active); if (bta_mce_cb.sdp_active != BTA_MCE_SDP_ACT_NONE) { /* SDP is still in progress */ status = BTA_MCE_BUSY; if(bta_mce_cb.p_dm_cback) bta_mce_cb.p_dm_cback(BTA_MCE_MAS_DISCOVERY_COMP_EVT, (tBTA_MCE *)&status, NULL); return; } bta_mce_cb.sdp_active = BTA_MCE_SDP_ACT_YES; bdcpy(bta_mce_cb.remote_addr, p_data->get_rmt_mas.bd_addr); SDP_InitDiscoveryDb (p_bta_mce_cfg->p_sdp_db, p_bta_mce_cfg->sdp_db_size, 1, (tBT_UUID*) &bta_mce_mas_uuid, 0, NULL); if (!SDP_ServiceSearchAttributeRequest2(p_data->get_rmt_mas.bd_addr, p_bta_mce_cfg->p_sdp_db, bta_mce_search_cback, NULL)) { bta_mce_cb.sdp_active = BTA_MCE_SDP_ACT_NONE; /* failed to start SDP. report the failure right away */ if (bta_mce_cb.p_dm_cback) bta_mce_cb.p_dm_cback(BTA_MCE_MAS_DISCOVERY_COMP_EVT, (tBTA_MCE *)&status, NULL); } /* else report the result when the cback is called */ }
/******************************************************************************* ** ** Function bta_av_co_audio_close ** ** Description This function is called by AV when the audio stream connection ** is closed. ** ** ** Returns void ** *******************************************************************************/ BTA_API void bta_av_co_audio_close(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type, UINT16 mtu) { tBTA_AV_CO_PEER *p_peer; FUNC_TRACE(); APPL_TRACE_DEBUG0("bta_av_co_audio_close"); /* Retrieve the peer info */ p_peer = bta_av_co_get_peer(hndl); if (p_peer) { /* Mark the peer closed and clean the peer info */ memset(p_peer, 0, sizeof(*p_peer)); } else { APPL_TRACE_ERROR0("bta_av_co_audio_close could not find peer entry"); } /* reset remote preference through setconfig */ bta_av_co_cb.codec_cfg_setconfig.id = BTIF_AV_CODEC_NONE; }
int bta_ma_co_open(const char *p_path, int oflags) { struct stat file_stat; int fd; /* Convert BTA oflags into MFS */ oflags = bta_fs_convert_bta_oflags(oflags); if ((fd = open (p_path, oflags | O_NONBLOCK, 0666)) < 0) { APPL_TRACE_ERROR2("%s: Error opening file: error code %d", __FUNCTION__, fd); return BTA_FS_INVALID_FD; } else { if(fstat(fd, &file_stat) == 0) { if (oflags & O_CREAT) { fchown(fd, BT_UID, BT_GID); APPL_TRACE_DEBUG0("\n ******CHANGED OWNERSHIP SUCCESSFULLY**********"); } } return fd; } }
/******************************************************************************* ** ** Function bta_av_co_audio_sink_has_scmst ** ** Description Check if a sink supports SCMS-T ** ** Returns TRUE if the sink supports this CP, FALSE otherwise ** *******************************************************************************/ static BOOLEAN bta_av_co_audio_sink_has_scmst(const tBTA_AV_CO_SINK *p_sink) { UINT8 index; const UINT8 *p; FUNC_TRACE(); /* Check if sink supports SCMS-T */ index = p_sink->num_protect; p = &p_sink->protect_info[0]; while (index) { if (bta_av_co_cp_is_scmst(p)) { return TRUE; } /* Move to the next SC */ p += *p + 1; /* Decrement the SC counter */ index--; } APPL_TRACE_DEBUG0("bta_av_co_audio_sink_has_scmst: SCMS-T not found"); return FALSE; }
static void jv_dm_cback(tBTA_JV_EVT event, tBTA_JV *p_data, void *user_data) { uint32_t id = (uint32_t)user_data; APPL_TRACE_DEBUG2("jv_dm_cback: event:%d, slot id:%d", event, id); switch(event) { case BTA_JV_CREATE_RECORD_EVT: { lock_slot(&slot_lock); rfc_slot_t* rs = find_rfc_slot_by_id(id); if(rs && create_server_sdp_record(rs)) { //now start the rfcomm server after sdp & channel # assigned BTA_JvRfcommStartServer(rs->security, rs->role, rs->scn, MAX_RFC_SESSION, rfcomm_cback, (void*)rs->id); } else if(rs) { APPL_TRACE_ERROR1("jv_dm_cback: cannot start server, slot found:%p", rs); cleanup_rfc_slot(rs); } unlock_slot(&slot_lock); break; } case BTA_JV_DISCOVERY_COMP_EVT: { rfc_slot_t* rs = NULL; lock_slot(&slot_lock); if(p_data->disc_comp.status == BTA_JV_SUCCESS && p_data->disc_comp.scn) { APPL_TRACE_DEBUG3("BTA_JV_DISCOVERY_COMP_EVT, slot id:%d, status:%d, scn:%d", id, p_data->disc_comp.status, p_data->disc_comp.scn); rs = find_rfc_slot_by_id(id); if(rs && rs->f.doing_sdp_request) { if(BTA_JvRfcommConnect(rs->security, rs->role, p_data->disc_comp.scn, rs->addr.address, rfcomm_cback, (void*)rs->id) == BTA_JV_SUCCESS) { rs->scn = p_data->disc_comp.scn; rs->f.doing_sdp_request = FALSE; if(!send_app_scn(rs)) cleanup_rfc_slot(rs); } else cleanup_rfc_slot(rs); } else if(rs) { APPL_TRACE_ERROR3("DISCOVERY_COMP_EVT no pending sdp request, slot id:%d, \ flag sdp pending:%d, flag sdp doing:%d", id, rs->f.pending_sdp_request, rs->f.doing_sdp_request); } } else { APPL_TRACE_ERROR3("DISCOVERY_COMP_EVT slot id:%d, failed to find channle, \ status:%d, scn:%d", id, p_data->disc_comp.status, p_data->disc_comp.scn); rs = find_rfc_slot_by_id(id); if(rs) cleanup_rfc_slot(rs); } rs = find_rfc_slot_by_pending_sdp(); if(rs) { APPL_TRACE_DEBUG0("BTA_JV_DISCOVERY_COMP_EVT, start another pending scn sdp request"); tSDP_UUID sdp_uuid; sdp_uuid.len = 16; memcpy(sdp_uuid.uu.uuid128, rs->service_uuid, sizeof(sdp_uuid.uu.uuid128)); BTA_JvStartDiscovery((UINT8*)rs->addr.address, 1, &sdp_uuid, (void*)rs->id); rs->f.pending_sdp_request = FALSE; rs->f.doing_sdp_request = TRUE; } unlock_slot(&slot_lock); break; }
/******************************************************************************* ** ** Function bta_hh_hdl_event ** ** Description HID host main event handling function. ** ** ** Returns void ** *******************************************************************************/ BOOLEAN bta_hh_hdl_event(BT_HDR *p_msg) { UINT8 index = BTA_HH_IDX_INVALID; tBTA_HH_DEV_CB *p_cb = NULL; APPL_TRACE_DEBUG1("RTKDBG:p_msg->event:(%d)", p_msg->event); switch (p_msg->event) { case BTA_HH_API_ENABLE_EVT: bta_hh_api_enable((tBTA_HH_DATA *) p_msg); break; case BTA_HH_API_DISABLE_EVT: bta_hh_api_disable(); break; case BTA_HH_DISC_CMPL_EVT: /* disable complete */ bta_hh_disc_cmpl(); break; #ifdef BLUETOOTH_RTK case BTA_HH_API_RM_DEV_EVT: APPL_TRACE_DEBUG0("BTA_HH_API_RM_DEV_EVT"); index = bta_hh_find_cb(((tBTA_HH_API_CONN *)p_msg)->bd_addr); if (index != BTA_HH_IDX_INVALID) p_cb = &bta_hh_cb.kdev[index]; if (p_cb != NULL && p_cb->is_le_device) { bta_hh_le_remove_dev_bg_conn(p_cb); bta_hh_sm_execute(p_cb, BTA_HH_API_CLOSE_EVT, NULL); bta_hh_clean_up_kdev(p_cb); } break; #endif default: /* all events processed in state machine need to find corresponding CB before proceed */ if (p_msg->event == BTA_HH_API_OPEN_EVT) { index = bta_hh_find_cb(((tBTA_HH_API_CONN *)p_msg)->bd_addr); } else if (p_msg->event == BTA_HH_API_MAINT_DEV_EVT) { /* if add device */ if (((tBTA_HH_MAINT_DEV *)p_msg)->sub_event == BTA_HH_ADD_DEV_EVT) { index = bta_hh_find_cb(((tBTA_HH_MAINT_DEV *)p_msg)->bda); } else /* else remove device by handle */ { index = bta_hh_dev_handle_to_cb_idx((UINT8)p_msg->layer_specific); // btla-specific ++ /* If BT disable is done while the HID device is connected and Link_Key uses unauthenticated combination * then we can get into a situation where remove_bonding is called with the index set to 0 (without getting * cleaned up). Only when VIRTUAL_UNPLUG is called do we cleanup the index and make it MAX_KNOWN. * So if REMOVE_DEVICE is called and in_use is FALSE then we should treat this as a NULL p_cb. Hence we * force the index to be IDX_INVALID */ if ((index != BTA_HH_IDX_INVALID) && (bta_hh_cb.kdev[index].in_use == FALSE)) { index = BTA_HH_IDX_INVALID; } // btla-specific -- } } else if (p_msg->event == BTA_HH_INT_OPEN_EVT) { index = bta_hh_find_cb(((tBTA_HH_CBACK_DATA *)p_msg)->addr); } else index = bta_hh_dev_handle_to_cb_idx((UINT8)p_msg->layer_specific); if (index != BTA_HH_IDX_INVALID) p_cb = &bta_hh_cb.kdev[index]; #if BTA_HH_DEBUG APPL_TRACE_DEBUG2("bta_hh_hdl_event:: handle = %d dev_cb[%d] ", p_msg->layer_specific, index); #endif bta_hh_sm_execute(p_cb, p_msg->event, (tBTA_HH_DATA *) p_msg); } return (TRUE); }
/******************************************************************************* ** ** Function bta_hh_start_sdp ** ** Description Start SDP service search, and obtain necessary SDP records. ** Only one SDP service search request is allowed at the same ** time. For every BTA_HhOpen API call, do SDP first unless SDP ** has been done previously. ** ** Returns void ** *******************************************************************************/ void bta_hh_start_sdp(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data) { tBTA_HH_STATUS status = BTA_HH_ERR_SDP; UINT8 hdl; p_cb->sec_mask = p_data->api_conn.sec_mask; p_cb->mode = p_data->api_conn.mode; bta_hh_cb.p_cur = p_cb; /* if previously virtually cabled device, skip SDP */ if (p_cb->app_id) { status = BTA_HH_OK; #if BTA_HH_DEBUG APPL_TRACE_DEBUG0("bta_hh_start_sdp:: skip SDP for known devices"); #endif if (p_cb->hid_handle == BTA_HH_INVALID_HANDLE) { if ((HID_HostAddDev (p_cb->addr, p_cb->attr_mask, &hdl)) \ == HID_SUCCESS) { /* update device CB with newly register device handle */ bta_hh_add_device_to_list(p_cb, hdl, p_cb->attr_mask, NULL, p_cb->sub_class, p_cb->dscp_info.ssr_max_latency, p_cb->dscp_info.ssr_min_tout, p_cb->app_id); /* update cb_index[] map */ bta_hh_cb.cb_index[hdl] = p_cb->index; } else status = BTA_HH_ERR_NO_RES; } bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, (tBTA_HH_DATA *)&status); return; } /* GetSDPRecord. at one time only one SDP precedure can be active */ else if (!bta_hh_cb.p_disc_db) { bta_hh_cb.p_disc_db = (tSDP_DISCOVERY_DB *) GKI_getbuf(p_bta_hh_cfg->sdp_db_size); if (bta_hh_cb.p_disc_db == NULL) { status = BTA_HH_ERR_NO_RES; } else { bta_hh_cb.p_cur = p_cb; /* do DI discovery first */ if (SDP_DiDiscover(p_data->api_conn.bd_addr, bta_hh_cb.p_disc_db, p_bta_hh_cfg->sdp_db_size, bta_hh_di_sdp_cback) != SDP_SUCCESS) { #if BTA_HH_DEBUG APPL_TRACE_DEBUG1 ("bta_hh_start_sdp: SDP_DiDiscover failed: \ Status 0x%2X",status); #endif status = BTA_HH_ERR_SDP; utl_freebuf((void **)&bta_hh_cb.p_disc_db); } else
/******************************************************************************* ** ** Function GKI_run ** ** Description This function runs a task ** ** Parameters: p_task_id - (input) pointer to task id ** ** Returns void ** ** NOTE This function is only needed for operating systems where ** starting a task is a 2-step process. Most OS's do it in ** one step, If your OS does it in one step, this function ** should be empty. *********************************************************************************/ void GKI_run (void *p_task_id) { GKI_TRACE_1("%s enter", __func__); struct timespec delay; int err = 0; volatile int * p_run_cond = &gki_cb.os.no_timer_suspend; #ifndef GKI_NO_TICK_STOP /* register start stop function which disable timer loop in GKI_run() when no timers are * in any GKI/BTA/BTU this should save power when BTLD is idle! */ GKI_timer_queue_register_callback( gki_system_tick_start_stop_cback ); APPL_TRACE_DEBUG0( "GKI_run(): Start/Stop GKI_timer_update_registered!" ); #endif #ifdef NO_GKI_RUN_RETURN GKI_TRACE_0("GKI_run == NO_GKI_RUN_RETURN"); pthread_attr_t timer_attr; shutdown_timer = 0; pthread_attr_init(&timer_attr); pthread_attr_setdetachstate(&timer_attr, PTHREAD_CREATE_DETACHED); if (pthread_create( &timer_thread_id, &timer_attr, timer_thread, NULL) != 0 ) { GKI_TRACE_0("GKI_run: pthread_create failed to create timer_thread!"); return GKI_FAILURE; } #else GKI_TRACE_2("GKI_run, run_cond(%x)=%d ", p_run_cond, *p_run_cond); for (;GKI_TIMER_TICK_EXIT_COND != *p_run_cond;) { do { /* adjust hear bit tick in btld by changning TICKS_PER_SEC!!!!! this formula works only for * 1-1000ms heart beat units! */ delay.tv_sec = LINUX_SEC / 1000; delay.tv_nsec = 1000 * 1000 * (LINUX_SEC % 1000); /* [u]sleep can't be used because it uses SIGALRM */ do { err = nanosleep(&delay, &delay); } while (err < 0 && errno == EINTR); /* the unit should be alsways 1 (1 tick). only if you vary for some reason heart beat tick * e.g. power saving you may want to provide more ticks */ GKI_timer_update( 1 ); /* BT_TRACE_2( TRACE_LAYER_HCI, TRACE_TYPE_DEBUG, "update: tv_sec: %d, tv_nsec: %d", delay.tv_sec, delay.tv_nsec ); */ } while ( GKI_TIMER_TICK_RUN_COND == *p_run_cond); /* currently on reason to exit above loop is no_timer_suspend == GKI_TIMER_TICK_STOP_COND * block timer main thread till re-armed by */ #ifdef GKI_TICK_TIMER_DEBUG BT_TRACE_0( TRACE_LAYER_HCI, TRACE_TYPE_DEBUG, ">>> SUSPENDED GKI_timer_update()" ); #endif if (GKI_TIMER_TICK_EXIT_COND != *p_run_cond) { GKI_TRACE_1("%s waiting timer mutex", __func__); pthread_mutex_lock( &gki_cb.os.gki_timer_mutex ); pthread_cond_wait( &gki_cb.os.gki_timer_cond, &gki_cb.os.gki_timer_mutex ); pthread_mutex_unlock( &gki_cb.os.gki_timer_mutex ); GKI_TRACE_1("%s exited timer mutex", __func__); } /* potentially we need to adjust os gki_cb.com.OSTicks */ #ifdef GKI_TICK_TIMER_DEBUG BT_TRACE_1( TRACE_LAYER_HCI, TRACE_TYPE_DEBUG, ">>> RESTARTED GKI_timer_update(): run_cond: %d", *p_run_cond ); #endif } /* for */ #endif GKI_TRACE_1("%s exit", __func__); return(0); }
/******************************************************************************* ** ** Function bta_av_co_audio_stop ** ** Description This function is called by AV when the audio streaming data ** transfer is stopped. ** ** ** Returns void ** *******************************************************************************/ BTA_API extern void bta_av_co_audio_stop(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type) { FUNC_TRACE(); APPL_TRACE_DEBUG0("bta_av_co_audio_stop"); }
/******************************************************************************* ** ** Function bta_av_co_audio_codec_supported ** ** Description Check if all opened connections are compatible with a codec ** configuration and content protection ** ** Returns TRUE if all opened devices support this codec, FALSE otherwise ** *******************************************************************************/ BOOLEAN bta_av_co_audio_codec_supported(tBTIF_STATUS *p_status) { UINT8 index; UINT8 snk_index; tBTA_AV_CO_PEER *p_peer; tBTA_AV_CO_SINK *p_sink; UINT8 codec_cfg[AVDT_CODEC_SIZE]; UINT8 num_protect = 0; #if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE) BOOLEAN cp_active; #endif FUNC_TRACE(); APPL_TRACE_DEBUG0("bta_av_co_audio_codec_supported"); /* Check AV feeding is supported */ *p_status = BTIF_ERROR_SRV_AV_FEEDING_NOT_SUPPORTED; for (index = 0; index < BTA_AV_CO_NUM_ELEMENTS(bta_av_co_cb.peers); index++) { p_peer = &bta_av_co_cb.peers[index]; if (p_peer->opened) { if (bta_av_co_audio_peer_supports_codec(p_peer, &snk_index)) { p_sink = &p_peer->snks[snk_index]; /* Check that this sink is compatible with the CP */ if (!bta_av_co_audio_sink_supports_cp(p_sink)) { APPL_TRACE_DEBUG2("bta_av_co_audio_codec_supported sink %d of peer %d doesn't support cp", snk_index, index); *p_status = BTIF_ERROR_SRV_AV_CP_NOT_SUPPORTED; return FALSE; } /* Build the codec configuration for this sink */ if (bta_av_co_audio_codec_build_config(p_sink->codec_caps, codec_cfg)) { #if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE) /* Check if this sink supports SCMS */ cp_active = bta_av_co_audio_sink_has_scmst(p_sink); #endif /* Check if this is a new configuration (new sink or new config) */ if ((p_sink != p_peer->p_snk) || (memcmp(codec_cfg, p_peer->codec_cfg, AVDT_CODEC_SIZE)) #if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE) || (p_peer->cp_active != cp_active) #endif ) { /* Save the new configuration */ p_peer->p_snk = p_sink; memcpy(p_peer->codec_cfg, codec_cfg, AVDT_CODEC_SIZE); #if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE) p_peer->cp_active = cp_active; if (p_peer->cp_active) { bta_av_co_cb.cp.active = TRUE; num_protect = BTA_AV_CP_INFO_LEN; } else { bta_av_co_cb.cp.active = FALSE; } #endif APPL_TRACE_DEBUG1("bta_av_co_audio_codec_supported call BTA_AvReconfig(x%x)", BTA_AV_CO_AUDIO_INDX_TO_HNDL(index)); BTA_AvReconfig(BTA_AV_CO_AUDIO_INDX_TO_HNDL(index), TRUE, p_sink->sep_info_idx, p_peer->codec_cfg, num_protect, (UINT8 *)bta_av_co_cp_scmst); } } } else { APPL_TRACE_DEBUG1("bta_av_co_audio_codec_supported index %d doesn't support codec", index); return FALSE; } } } *p_status = BTIF_SUCCESS; return TRUE; }
/******************************************************************************* ** ** Function bta_av_co_audio_getconfig ** ** Description This callout function is executed by AV to retrieve the ** desired codec and content protection configuration for the ** audio stream. ** ** ** Returns Stream codec and content protection configuration info. ** *******************************************************************************/ BTA_API UINT8 bta_av_co_audio_getconfig(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type, UINT8 *p_codec_info, UINT8 *p_sep_info_idx, UINT8 seid, UINT8 *p_num_protect, UINT8 *p_protect_info) { UINT8 result = A2D_FAIL; BOOLEAN supported; tBTA_AV_CO_PEER *p_peer; tBTA_AV_CO_SINK *p_sink; UINT8 codec_cfg[AVDT_CODEC_SIZE]; UINT8 index; FUNC_TRACE(); APPL_TRACE_DEBUG3("bta_av_co_audio_getconfig handle:0x%x codec_type:%d seid:%d", hndl, codec_type, seid); APPL_TRACE_DEBUG4("num_protect:0x%02x protect_info:0x%02x%02x%02x", *p_num_protect, p_protect_info[0], p_protect_info[1], p_protect_info[2]); /* Retrieve the peer info */ p_peer = bta_av_co_get_peer(hndl); if (p_peer == NULL) { APPL_TRACE_ERROR0("bta_av_co_audio_getconfig could not find peer entry"); return A2D_FAIL; } APPL_TRACE_DEBUG4("bta_av_co_audio_getconfig peer(o=%d,n_snks=%d,n_rx_snks=%d,n_sup_snks=%d)", p_peer->opened, p_peer->num_snks, p_peer->num_rx_snks, p_peer->num_sup_snks); /* Increment the number of received sinks capabilities */ p_peer->num_rx_snks++; /* Check if this is a supported configuration */ supported = FALSE; switch (codec_type) { case BTA_AV_CODEC_SBC: supported = TRUE; break; default: break; } if (supported) { /* If there is room for a new one */ if (p_peer->num_sup_snks < BTA_AV_CO_NUM_ELEMENTS(p_peer->snks)) { p_sink = &p_peer->snks[p_peer->num_sup_snks++]; APPL_TRACE_DEBUG6("bta_av_co_audio_getconfig saved caps[%x:%x:%x:%x:%x:%x]", p_codec_info[1], p_codec_info[2], p_codec_info[3], p_codec_info[4], p_codec_info[5], p_codec_info[6]); memcpy(p_sink->codec_caps, p_codec_info, AVDT_CODEC_SIZE); p_sink->codec_type = codec_type; p_sink->sep_info_idx = *p_sep_info_idx; p_sink->seid = seid; p_sink->num_protect = *p_num_protect; memcpy(p_sink->protect_info, p_protect_info, BTA_AV_CP_INFO_LEN); } else { APPL_TRACE_ERROR0("bta_av_co_audio_getconfig no more room for SNK info"); } } /* If last SNK get capabilities or all supported codec capa retrieved */ if ((p_peer->num_rx_snks == p_peer->num_snks) || (p_peer->num_sup_snks == BTA_AV_CO_NUM_ELEMENTS(p_peer->snks))) { APPL_TRACE_DEBUG0("bta_av_co_audio_getconfig last sink reached"); /* Protect access to bta_av_co_cb.codec_cfg */ GKI_disable(); /* Find a sink that matches the codec config */ if (bta_av_co_audio_peer_supports_codec(p_peer, &index)) { /* stop fetching caps once we retrieved a supported codec */ if (p_peer->acp) { *p_sep_info_idx = p_peer->num_seps; APPL_TRACE_EVENT0("no need to fetch more SEPs"); } p_sink = &p_peer->snks[index]; /* Build the codec configuration for this sink */ if (bta_av_co_audio_codec_build_config(p_sink->codec_caps, codec_cfg)) { APPL_TRACE_DEBUG6("bta_av_co_audio_getconfig reconfig p_codec_info[%x:%x:%x:%x:%x:%x]", codec_cfg[1], codec_cfg[2], codec_cfg[3], codec_cfg[4], codec_cfg[5], codec_cfg[6]); /* Save the new configuration */ p_peer->p_snk = p_sink; memcpy(p_peer->codec_cfg, codec_cfg, AVDT_CODEC_SIZE); /* By default, no content protection */ *p_num_protect = 0; #if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE) /* Check if this sink supports SCMS */ if (bta_av_co_audio_sink_has_scmst(p_sink)) { p_peer->cp_active = TRUE; bta_av_co_cb.cp.active = TRUE; *p_num_protect = BTA_AV_CP_INFO_LEN; memcpy(p_protect_info, bta_av_co_cp_scmst, BTA_AV_CP_INFO_LEN); } else { p_peer->cp_active = FALSE; bta_av_co_cb.cp.active = FALSE; } #endif /* If acceptor -> reconfig otherwise reply for configuration */ if (p_peer->acp) { if (p_peer->recfg_needed) { APPL_TRACE_DEBUG1("bta_av_co_audio_getconfig call BTA_AvReconfig(x%x)", hndl); BTA_AvReconfig(hndl, TRUE, p_sink->sep_info_idx, p_peer->codec_cfg, *p_num_protect, (UINT8 *)bta_av_co_cp_scmst); } } else { *p_sep_info_idx = p_sink->sep_info_idx; memcpy(p_codec_info, p_peer->codec_cfg, AVDT_CODEC_SIZE); } result = A2D_SUCCESS; } } /* Protect access to bta_av_co_cb.codec_cfg */ GKI_enable(); } return result; }