static uint32_t on_srv_rfc_connect(tBTA_JV_RFCOMM_SRV_OPEN *p_open, uint32_t id) { uint32_t new_listen_slot_id = 0; lock_slot(&slot_lock); rfc_slot_t* srv_rs = find_rfc_slot_by_id(id); if(srv_rs) { rfc_slot_t* accept_rs = create_srv_accept_rfc_slot(srv_rs, (const bt_bdaddr_t*)p_open->rem_bda, p_open->handle, p_open->new_listen_handle); if(accept_rs) { //start monitor the socket btsock_thread_add_fd(pth, srv_rs->fd, BTSOCK_RFCOMM, SOCK_THREAD_FD_EXCEPTION, srv_rs->id); btsock_thread_add_fd(pth, accept_rs->fd, BTSOCK_RFCOMM, SOCK_THREAD_FD_RD, accept_rs->id); APPL_TRACE_DEBUG1("sending connect signal & app fd:%dto app server to accept() the connection", accept_rs->app_fd); APPL_TRACE_DEBUG2("server fd:%d, scn:%d", srv_rs->fd, srv_rs->scn); send_app_connect_signal(srv_rs->fd, &accept_rs->addr, srv_rs->scn, 0, accept_rs->app_fd); accept_rs->app_fd = -1; //the fd is closed after sent to app new_listen_slot_id = srv_rs->id; } } unlock_slot(&slot_lock); return new_listen_slot_id; }
static void bta_hf_client_dump_at(void) { char dump[(4 * BTA_HF_CLIENT_AT_PARSER_MAX_LEN) + 1]; char *p1, *p2; p1 = bta_hf_client_cb.scb.at_cb.buf; p2 = dump; while (*p1 != '\0') { if (*p1 == '\r') { strlcpy(p2, "<cr>", 4); p2 += 4; } else if (*p1 == '\n') { strlcpy(p2, "<lf>", 4); p2 += 4; } else { *p2 = *p1; p2++; } p1++; } *p2 = '\0'; APPL_TRACE_DEBUG2("%s %s", __FUNCTION__, dump); }
/******************************************************************************* ** ** Function bta_hf_client_remove_sco ** ** Description Removes the specified SCO from the system. ** If only_active is TRUE, then SCO is only removed if connected ** ** Returns BOOLEAN - TRUE if Sco removal was started ** *******************************************************************************/ static BOOLEAN bta_hf_client_sco_remove(BOOLEAN only_active) { BOOLEAN removed_started = FALSE; tBTM_STATUS status; APPL_TRACE_DEBUG2("%s %d", __FUNCTION__, only_active); if (bta_hf_client_cb.scb.sco_idx != BTM_INVALID_SCO_INDEX) { status = BTM_RemoveSco(bta_hf_client_cb.scb.sco_idx); APPL_TRACE_DEBUG3("%s idx 0x%04x, status:0x%x", __FUNCTION__, bta_hf_client_cb.scb.sco_idx, status); if (status == BTM_CMD_STARTED) { removed_started = TRUE; } /* If no connection reset the sco handle */ else if ( (status == BTM_SUCCESS) || (status == BTM_UNKNOWN_ADDR) ) { bta_hf_client_cb.scb.sco_idx = BTM_INVALID_SCO_INDEX; } } return removed_started; }
/******************************************************************************* ** ** Function bta_hf_client_sco_conn_cback ** ** Description BTM SCO connection callback. ** ** ** Returns void ** *******************************************************************************/ static void bta_hf_client_sco_conn_cback(UINT16 sco_idx) { BT_HDR *p_buf; UINT8 *rem_bd; APPL_TRACE_DEBUG2("%s %d", __FUNCTION__, sco_idx); rem_bd = BTM_ReadScoBdAddr(sco_idx); if (rem_bd && bdcmp(bta_hf_client_cb.scb.peer_addr, rem_bd) == 0 && bta_hf_client_cb.scb.svc_conn && bta_hf_client_cb.scb.sco_idx == sco_idx) { if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL) { p_buf->event = BTA_HF_CLIENT_SCO_OPEN_EVT; p_buf->layer_specific = bta_hf_client_cb.scb.conn_handle; bta_sys_sendmsg(p_buf); } } /* no match found; disconnect sco, init sco variables */ else { bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST; BTM_RemoveSco(sco_idx); } }
int btsock_thread_create(btsock_signaled_cb callback, btsock_cmd_cb cmd_callback) { int ret = FALSE; asrt(callback || cmd_callback); lock_slot(&thread_slot_lock); int h = alloc_thread_slot(); unlock_slot(&thread_slot_lock); APPL_TRACE_DEBUG1("alloc_thread_slot ret:%d", h); if(h >= 0) { init_poll(h); if((ts[h].thread_id = create_thread(sock_poll_thread, (void*)h)) != -1) { APPL_TRACE_DEBUG2("h:%d, thread id:%d", h, ts[h].thread_id); ts[h].callback = callback; ts[h].cmd_callback = cmd_callback; } else { free_thread_slot(h); h = -1; } } return h; }
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); }
static inline int accept_server_socket(int s) { struct sockaddr_un client_address; socklen_t clen; int fd = accept(s, (struct sockaddr*)&client_address, &clen); APPL_TRACE_DEBUG2("accepted fd:%d for server fd:%d", fd, s); return fd; }
/******************************************************************************* ** ** Function bta_fs_co_close ** ** Description This function is called by BTA when a connection to a ** client is closed. ** ** Parameters fd - file descriptor of file to close. ** ** Returns void *******************************************************************************/ void bta_ma_co_close(int fd) { INT32 status; APPL_TRACE_DEBUG2("%s: fd:%d",__FUNCTION__,fd); if ((status = close (fd)) < 0) { APPL_TRACE_ERROR3("%s: fd:%d error=%d", __FUNCTION__, fd, errno); } }
/******************************************************************************* ** ** Function bta_hf_client_sco_close ** ** Description ** ** ** Returns void ** *******************************************************************************/ void bta_hf_client_sco_close(tBTA_HF_CLIENT_DATA *p_data) { APPL_TRACE_DEBUG2("%s 0x%x", __FUNCTION__, bta_hf_client_cb.scb.sco_idx); if (bta_hf_client_cb.scb.sco_idx != BTM_INVALID_SCO_INDEX) { bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_CLOSE_E); } }
static void bta_hf_client_handle_vgs(UINT32 value) { APPL_TRACE_DEBUG2("%s %lu", __FUNCTION__, value); if(value <= BTA_HF_CLIENT_VGS_MAX) { bta_hf_client_evt_val(BTA_HF_CLIENT_SPK_EVT, value); } }
static void bta_hf_client_handle_bvra(UINT32 value) { APPL_TRACE_DEBUG2("%s %lu", __FUNCTION__, value); if (value > 1) { return; } bta_hf_client_evt_val(BTA_HF_CLIENT_VOICE_REC_EVT, value); }
static inline int connect_server_socket(const char* name) { int s = socket(AF_LOCAL, SOCK_STREAM, 0); set_socket_blocking(s, TRUE); if(socket_local_client_connect(s, name, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM) >= 0) { APPL_TRACE_DEBUG2("connected to local socket:%s, fd:%d", name, s); return s; } else APPL_TRACE_ERROR3("connect to local socket:%s, fd:%d failed, errno:%d", name, s, errno); close(s); return -1; }
void bta_av_conn_cback(UINT8 handle, BD_ADDR bd_addr, UINT8 event, tAVDT_CTRL *p_data) { tBTA_AV_STR_MSG *p_msg; UINT16 evt = 0; tBTA_AV_SCB *p_scb = NULL; #if( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == TRUE) if (event == BTA_AR_AVDT_CONN_EVT || event == AVDT_CONNECT_IND_EVT || event == AVDT_DISCONNECT_IND_EVT) #else if (event == AVDT_CONNECT_IND_EVT || event == AVDT_DISCONNECT_IND_EVT) #endif { evt = BTA_AV_SIG_CHG_EVT; if(AVDT_DISCONNECT_IND_EVT == event) p_scb = bta_av_addr_to_scb(bd_addr); #if (defined(BTA_AV_DEBUG) && BTA_AV_DEBUG == TRUE) else if (AVDT_CONNECT_IND_EVT == event) { APPL_TRACE_DEBUG1("CONN_IND is ACP:%d", p_data->hdr.err_param); } #endif if (/*((p_scb && (p_scb->role & BTA_AV_ROLE_AD_ACP)) || //(AVDT_CONNECT_IND_EVT == event && AVDT_ACP == p_data->hdr.err_param)) (AVDT_CONNECT_IND_EVT == event))&& */ (p_msg = (tBTA_AV_STR_MSG *) GKI_getbuf((UINT16) (sizeof(tBTA_AV_STR_MSG)))) != NULL) { p_msg->hdr.event = evt; p_msg->hdr.layer_specific = event; p_msg->hdr.offset = p_data->hdr.err_param; bdcpy(p_msg->bd_addr, bd_addr); #if (defined(BTA_AV_DEBUG) && BTA_AV_DEBUG == TRUE) if(p_scb) { APPL_TRACE_DEBUG2("scb hndl x%x, role x%x", p_scb->hndl, p_scb->role); } #endif APPL_TRACE_DEBUG6("conn_cback bd_addr:%02x-%02x-%02x-%02x-%02x-%02x", bd_addr[0], bd_addr[1], bd_addr[2], bd_addr[3], bd_addr[4], bd_addr[5]); bta_sys_sendmsg(p_msg); } } }
/******************************************************************************* ** ** Function bta_hf_client_sco_disc_cback ** ** Description BTM SCO disconnection callback. ** ** ** Returns void ** *******************************************************************************/ static void bta_hf_client_sco_disc_cback(UINT16 sco_idx) { BT_HDR *p_buf; APPL_TRACE_DEBUG2("%s %d", __FUNCTION__, sco_idx); if (bta_hf_client_cb.scb.sco_idx == sco_idx) { if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL) { p_buf->event = BTA_HF_CLIENT_SCO_CLOSE_EVT; p_buf->layer_specific = bta_hf_client_cb.scb.conn_handle;; bta_sys_sendmsg(p_buf); } } }
static void bta_hf_client_handle_bcs(UINT32 codec) { APPL_TRACE_DEBUG2("%s %u", __FUNCTION__, codec); if (codec == BTM_SCO_CODEC_CVSD || (codec == BTM_SCO_CODEC_MSBC && bta_hf_client_cb.msbc_enabled == TRUE)) { bta_hf_client_cb.scb.negotiated_codec = codec; bta_hf_client_send_at_bcs(codec); } else { bta_hf_client_cb.scb.negotiated_codec = BTM_SCO_CODEC_CVSD; bta_hf_client_send_at_bac(); } }
static int alloc_thread_slot() { int i; //revserd order to save guard uninitialized access to 0 index for(i = MAX_THREAD - 1; i >=0; i--) { APPL_TRACE_DEBUG2("ts[%d].used:%d", i, ts[i].used); if(!ts[i].used) { ts[i].used = 1; return i; } } APPL_TRACE_ERROR0("execeeded max thread count"); return -1; }
static BOOLEAN bta_hf_client_check_at_complete(void) { BOOLEAN ret = FALSE; tBTA_HF_CLIENT_AT_CB *at_cb = &bta_hf_client_cb.scb.at_cb; if (at_cb->offset >= BTA_HF_CLIENT_AT_EVENT_MIN_LEN) { if (at_cb->buf[at_cb->offset - 2] == '\r' && at_cb->buf[at_cb->offset - 1] == '\n') { ret = TRUE; } } APPL_TRACE_DEBUG2("%s %d", __FUNCTION__, ret); return ret; }
static inline int create_server_socket(const char* name) { int s = socket(AF_LOCAL, SOCK_STREAM, 0); APPL_TRACE_DEBUG1("covert name to android abstract name:%s", name); if(socket_local_server_bind(s, name, ANDROID_SOCKET_NAMESPACE_ABSTRACT) >= 0) { if(listen(s, 5) == 0) { APPL_TRACE_DEBUG2("listen to local socket:%s, fd:%d", name, s); return s; } else APPL_TRACE_ERROR3("listen to local socket:%s, fd:%d failed, errno:%d", name, s, errno); } else APPL_TRACE_ERROR3("create local socket:%s fd:%d, failed, errno:%d", name, s, errno); close(s); return -1; }
/******************************************************************************* ** ** Function bta_hf_client_sco_connreq_cback ** ** Description BTM eSCO connection requests and eSCO change requests ** Only the connection requests are processed by BTA. ** ** Returns void ** *******************************************************************************/ static void bta_hf_client_esco_connreq_cback(tBTM_ESCO_EVT event, tBTM_ESCO_EVT_DATA *p_data) { APPL_TRACE_DEBUG2("%s %d", __FUNCTION__, event); if (event != BTM_ESCO_CONN_REQ_EVT) { return; } /* TODO check remote bdaddr, should allow connect only from device with * active SLC */ bta_hf_client_cb.scb.sco_idx = p_data->conn_evt.sco_inx; bta_hf_client_sco_conn_rsp(&p_data->conn_evt); bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPENING_ST; }
/******************************************************************************* ** ** Function bta_av_sco_chg_cback ** ** Description receive & process the SCO connection up/down event from sys. ** call setup also triggers this callback, to suspend av before sco ** activity happens, or to resume av once call ends. ** ** Returns void ** *******************************************************************************/ static void bta_av_sco_chg_cback(tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8 app_id, BD_ADDR peer_addr) { tBTA_AV_SCB *p_scb; int i; tBTA_AV_API_STOP stop; APPL_TRACE_DEBUG2("bta_av_sco_chg_cback:%d status:%d", id, status); if(id) { bta_av_cb.sco_occupied = TRUE; /* either BTA_SYS_SCO_OPEN or BTA_SYS_SCO_CLOSE with remaining active SCO */ for(i=0; i<BTA_AV_NUM_STRS; i++) { p_scb = bta_av_cb.p_scb[i]; if( p_scb && p_scb->co_started && (p_scb->sco_suspend == FALSE)) { APPL_TRACE_DEBUG1("suspending scb:%d", i); /* scb is used and started, not suspended automatically */ p_scb->sco_suspend = TRUE; stop.flush = FALSE; stop.suspend = TRUE; bta_av_ssm_execute(p_scb, BTA_AV_AP_STOP_EVT, (tBTA_AV_DATA *)&stop); } } } else { bta_av_cb.sco_occupied = FALSE; for(i=0; i<BTA_AV_NUM_STRS; i++) { p_scb = bta_av_cb.p_scb[i]; if( p_scb && p_scb->sco_suspend ) /* scb is used and suspended for SCO */ { APPL_TRACE_DEBUG1("starting scb:%d", i); bta_av_ssm_execute(p_scb, BTA_AV_AP_START_EVT, NULL); } } } }
/******************************************************************************* ** ** Function bta_av_co_audio_open ** ** Description This function is called by AV when the audio stream connection ** is opened. ** ** ** Returns void ** *******************************************************************************/ BTA_API void bta_av_co_audio_open(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type, UINT8 *p_codec_info, UINT16 mtu) { tBTA_AV_CO_PEER *p_peer; FUNC_TRACE(); APPL_TRACE_DEBUG2("bta_av_co_audio_open mtu:%d codec_type:%d", mtu, codec_type); /* Retrieve the peer info */ p_peer = bta_av_co_get_peer(hndl); if (p_peer == NULL) { APPL_TRACE_ERROR0("bta_av_co_audio_setconfig could not find peer entry"); } else { p_peer->opened = TRUE; p_peer->mtu = mtu; } }
/******************************************************************************* ** ** 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 */ }
static void bta_hf_client_handle_binp(char *numstr) { APPL_TRACE_DEBUG2("%s %s", __FUNCTION__, numstr); bta_hf_client_binp(numstr); }
static void bta_hf_client_handle_btrh( UINT16 code) { APPL_TRACE_DEBUG2("%s %lu", __FUNCTION__, code); bta_hf_client_evt_val(BTA_HF_CLIENT_BTRH_EVT, code); }
/******************************************************************************* ** ** 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_hf_client_create_sco ** ** Description ** ** ** Returns void ** *******************************************************************************/ static void bta_hf_client_sco_create(BOOLEAN is_orig) { tBTM_STATUS status; UINT8 *p_bd_addr = NULL; tBTM_ESCO_PARAMS params; APPL_TRACE_DEBUG2("%s %d", __FUNCTION__, is_orig); /* Make sure this sco handle is not already in use */ if (bta_hf_client_cb.scb.sco_idx != BTM_INVALID_SCO_INDEX) { APPL_TRACE_WARNING2("%s: Index 0x%04x already in use", __FUNCTION__, bta_hf_client_cb.scb.sco_idx); return; } params = bta_hf_client_esco_params[1]; /* if initiating set current scb and peer bd addr */ if (is_orig) { /* Attempt to use eSCO if remote host supports HFP >= 1.5 */ if (bta_hf_client_cb.scb.peer_version >= HFP_VERSION_1_5 && !bta_hf_client_cb.scb.retry_with_sco_only) { BTM_SetEScoMode(BTM_LINK_TYPE_ESCO, ¶ms); /* If ESCO or EDR ESCO, retry with SCO only in case of failure */ if((params.packet_types & BTM_ESCO_LINK_ONLY_MASK) ||!((params.packet_types & ~(BTM_ESCO_LINK_ONLY_MASK | BTM_SCO_LINK_ONLY_MASK)) ^ BTA_HF_CLIENT_NO_EDR_ESCO)) { bta_hf_client_cb.scb.retry_with_sco_only = TRUE; APPL_TRACE_API0("Setting retry_with_sco_only to TRUE"); } } else { if(bta_hf_client_cb.scb.retry_with_sco_only) APPL_TRACE_API0("retrying with SCO only"); bta_hf_client_cb.scb.retry_with_sco_only = FALSE; BTM_SetEScoMode(BTM_LINK_TYPE_SCO, ¶ms); } /* tell sys to stop av if any */ bta_sys_sco_use(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr); } else { bta_hf_client_cb.scb.retry_with_sco_only = FALSE; } p_bd_addr = bta_hf_client_cb.scb.peer_addr; status = BTM_CreateSco(p_bd_addr, is_orig, params.packet_types, &bta_hf_client_cb.scb.sco_idx, bta_hf_client_sco_conn_cback, bta_hf_client_sco_disc_cback); if (status == BTM_CMD_STARTED && !is_orig) { if(!BTM_RegForEScoEvts(bta_hf_client_cb.scb.sco_idx, bta_hf_client_esco_connreq_cback)) APPL_TRACE_DEBUG1("%s SCO registration success", __FUNCTION__); } APPL_TRACE_API5("%s: orig %d, inx 0x%04x, status 0x%x, pkt types 0x%04x", __FUNCTION__, is_orig, bta_hf_client_cb.scb.sco_idx, status, params.packet_types); }
/******************************************************************************* ** ** Function bta_av_co_audio_setconfig ** ** Description This callout function is executed by AV to set the codec and ** content protection configuration of the audio stream. ** ** ** Returns void ** *******************************************************************************/ BTA_API void bta_av_co_audio_setconfig(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type, UINT8 *p_codec_info, UINT8 seid, BD_ADDR addr, UINT8 num_protect, UINT8 *p_protect_info) { tBTA_AV_CO_PEER *p_peer; UINT8 status = A2D_SUCCESS; UINT8 category = A2D_SUCCESS; BOOLEAN recfg_needed = FALSE; FUNC_TRACE(); APPL_TRACE_DEBUG6("bta_av_co_audio_setconfig p_codec_info[%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]); APPL_TRACE_DEBUG4("num_protect:0x%02x protect_info:0x%02x%02x%02x", 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_setconfig could not find peer entry"); /* Call call-in rejecting the configuration */ bta_av_ci_setconfig(hndl, A2D_BUSY, AVDT_ASC_CODEC, 0, NULL, FALSE); return; } /* Sanity check: should not be opened at this point */ if (p_peer->opened) { APPL_TRACE_ERROR0("bta_av_co_audio_setconfig peer already in use"); } #if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE) if (num_protect != 0) { /* If CP is supported */ if ((num_protect != 1) || (bta_av_co_cp_is_scmst(p_protect_info) == FALSE)) { APPL_TRACE_ERROR0("bta_av_co_audio_setconfig wrong CP configuration"); status = A2D_BAD_CP_TYPE; category = AVDT_ASC_PROTECT; } } #else /* Do not support content protection for the time being */ if (num_protect != 0) { APPL_TRACE_ERROR0("bta_av_co_audio_setconfig wrong CP configuration"); status = A2D_BAD_CP_TYPE; category = AVDT_ASC_PROTECT; } #endif if (status == A2D_SUCCESS) { /* Check if codec configuration is supported */ if (bta_av_co_audio_media_supports_config(codec_type, p_codec_info)) { /* Protect access to bta_av_co_cb.codec_cfg */ GKI_disable(); /* Check if the configuration matches the current codec config */ switch (bta_av_co_cb.codec_cfg.id) { case BTIF_AV_CODEC_SBC: if ((codec_type != BTA_AV_CODEC_SBC) || memcmp(p_codec_info, bta_av_co_cb.codec_cfg.info, 5)) { recfg_needed = TRUE; } else if ((num_protect == 1) && (!bta_av_co_cb.cp.active)) { recfg_needed = TRUE; } /* if remote side requests a restricted notify sinks preferred bitpool range as all other params are already checked for validify */ APPL_TRACE_EVENT2("remote peer setconfig bitpool range [%d:%d]", p_codec_info[BTA_AV_CO_SBC_MIN_BITPOOL_OFF], p_codec_info[BTA_AV_CO_SBC_MAX_BITPOOL_OFF] ); bta_av_co_cb.codec_cfg_setconfig.id = BTIF_AV_CODEC_SBC; memcpy(bta_av_co_cb.codec_cfg_setconfig.info, p_codec_info, AVDT_CODEC_SIZE); break; default: APPL_TRACE_ERROR1("bta_av_co_audio_setconfig unsupported cid %d", bta_av_co_cb.codec_cfg.id); recfg_needed = TRUE; break; } /* Protect access to bta_av_co_cb.codec_cfg */ GKI_enable(); } else { category = AVDT_ASC_CODEC; status = A2D_WRONG_CODEC; } } if (status != A2D_SUCCESS) { APPL_TRACE_DEBUG2("bta_av_co_audio_setconfig reject s=%d c=%d", status, category); /* Call call-in rejecting the configuration */ bta_av_ci_setconfig(hndl, status, category, 0, NULL, FALSE); } else { /* Mark that this is an acceptor peer */ p_peer->acp = TRUE; p_peer->recfg_needed = recfg_needed; APPL_TRACE_DEBUG1("bta_av_co_audio_setconfig accept reconf=%d", recfg_needed); /* Call call-in accepting the configuration */ bta_av_ci_setconfig(hndl, A2D_SUCCESS, A2D_SUCCESS, 0, NULL, recfg_needed); } }
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_hl_sdp_register ** ** Purpose: Register an HDP application with SDP ** ** Parameters: p_cb - Pointer to MA instance control block ** p_service_name - MA server name ** inst_id - MAS instance ID ** msg_type - Supported message type(s) ** ** ** Returns: void ** *****************************************************************************/ tBTA_HL_STATUS bta_hl_sdp_register (UINT8 app_idx) { UINT16 svc_class_id_list[BTA_HL_NUM_SVC_ELEMS]; tSDP_PROTOCOL_ELEM proto_elem_list[BTA_HL_NUM_PROTO_ELEMS]; tSDP_PROTO_LIST_ELEM add_proto_list; tBTA_HL_SUP_FEATURE_LIST_ELEM sup_feature_list; UINT16 browse_list[] = {UUID_SERVCLASS_PUBLIC_BROWSE_GROUP}; UINT8 i,j, cnt,mdep_id, mdep_role; UINT8 data_exchange_spec = BTA_HL_SDP_IEEE_11073_20601; UINT8 mcap_sup_proc = BTA_HL_MCAP_SUP_PROC_MASK; UINT16 profile_uuid = UUID_SERVCLASS_HDP_PROFILE; UINT16 version = BTA_HL_VERSION_01_00; UINT8 num_services=1; tBTA_HL_APP_CB *p_cb = BTA_HL_GET_APP_CB_PTR(app_idx); BOOLEAN result = TRUE; tBTA_HL_STATUS status = BTA_HL_STATUS_OK; #if BTA_HL_DEBUG == TRUE APPL_TRACE_DEBUG1("bta_hl_sdp_register app_idx=%d",app_idx); #endif if ((p_cb->sup_feature.app_role_mask == BTA_HL_MDEP_ROLE_MASK_SOURCE) && (!p_cb->sup_feature.advertize_source_sdp)) { return BTA_HL_STATUS_OK; } if ((p_cb->sdp_handle = SDP_CreateRecord()) == 0) { return BTA_HL_STATUS_SDP_NO_RESOURCE; } num_services=1; svc_class_id_list[0]= UUID_SERVCLASS_HDP_SOURCE; if (p_cb->sup_feature.app_role_mask == BTA_HL_MDEP_ROLE_MASK_SINK) { svc_class_id_list[0]= UUID_SERVCLASS_HDP_SINK; } else { if (p_cb->sup_feature.app_role_mask != BTA_HL_MDEP_ROLE_MASK_SOURCE) { /* dual role */ num_services=2; svc_class_id_list[1]= UUID_SERVCLASS_HDP_SINK; } } result &= SDP_AddServiceClassIdList(p_cb->sdp_handle, num_services, svc_class_id_list); if (result) { /* add the protocol element sequence */ proto_elem_list[0].protocol_uuid = UUID_PROTOCOL_L2CAP; proto_elem_list[0].num_params = 1; proto_elem_list[0].params[0] = p_cb->ctrl_psm; proto_elem_list[1].protocol_uuid = UUID_PROTOCOL_MCAP_CTRL; proto_elem_list[1].num_params = 1; proto_elem_list[1].params[0] = version; result &= SDP_AddProtocolList(p_cb->sdp_handle, BTA_HL_NUM_PROTO_ELEMS, proto_elem_list); result &= SDP_AddProfileDescriptorList(p_cb->sdp_handle, profile_uuid, version); } if (result) { add_proto_list.num_elems = BTA_HL_NUM_ADD_PROTO_ELEMS; add_proto_list.list_elem[0].protocol_uuid = UUID_PROTOCOL_L2CAP; add_proto_list.list_elem[0].num_params = 1; add_proto_list.list_elem[0].params[0] = p_cb->data_psm; add_proto_list.list_elem[1].protocol_uuid = UUID_PROTOCOL_MCAP_DATA; add_proto_list.list_elem[1].num_params = 0; result &= SDP_AddAdditionProtoLists(p_cb->sdp_handle, BTA_HL_NUM_ADD_PROTO_LISTS, (tSDP_PROTO_LIST_ELEM *)&add_proto_list); } if (result) { if (p_cb->srv_name[0] ) { result &= SDP_AddAttribute(p_cb->sdp_handle, (UINT16)ATTR_ID_SERVICE_NAME, (UINT8)TEXT_STR_DESC_TYPE, (UINT32)(strlen(p_cb->srv_name) + 1), (UINT8 *)p_cb->srv_name); } /* end of setting optional service name */ } if (result) { if (p_cb->srv_desp[0] ) { result &= SDP_AddAttribute(p_cb->sdp_handle, (UINT16)ATTR_ID_SERVICE_DESCRIPTION, (UINT8)TEXT_STR_DESC_TYPE, (UINT32)(strlen(p_cb->srv_desp) + 1), (UINT8 *)p_cb->srv_desp); } /* end of setting optional service description */ } if (result) { if (p_cb->provider_name[0] ) { result &= SDP_AddAttribute(p_cb->sdp_handle, (UINT16)ATTR_ID_PROVIDER_NAME, (UINT8)TEXT_STR_DESC_TYPE, (UINT32)(strlen(p_cb->provider_name) + 1), (UINT8 *)p_cb->provider_name); } /* end of setting optional provider name */ } /* add supported feture list */ if (result) { cnt=0; for (i=1; i<= p_cb->sup_feature.num_of_mdeps; i++) { mdep_id = (UINT8)p_cb->sup_feature.mdep[i].mdep_id; mdep_role = (UINT8)p_cb->sup_feature.mdep[i].mdep_cfg.mdep_role; for (j=0; j<p_cb->sup_feature.mdep[i].mdep_cfg.num_of_mdep_data_types; j++) { sup_feature_list.list_elem[cnt].mdep_id = mdep_id; sup_feature_list.list_elem[cnt].mdep_role = mdep_role; sup_feature_list.list_elem[cnt].data_type = p_cb->sup_feature.mdep[i].mdep_cfg.data_cfg[j].data_type; if (p_cb->sup_feature.mdep[i].mdep_cfg.data_cfg[j].desp[0] != '\0') { sup_feature_list.list_elem[cnt].p_mdep_desp = p_cb->sup_feature.mdep[i].mdep_cfg.data_cfg[j].desp; } else { sup_feature_list.list_elem[cnt].p_mdep_desp = NULL; } cnt++; if (cnt==BTA_HL_NUM_SUP_FEATURE_ELEMS) { result = FALSE; break; } } } sup_feature_list.num_elems = cnt; result &= bta_hl_add_sup_feature_list (p_cb->sdp_handle, sup_feature_list.num_elems, sup_feature_list.list_elem); } if (result) { result &= SDP_AddAttribute(p_cb->sdp_handle, ATTR_ID_HDP_DATA_EXCH_SPEC, UINT_DESC_TYPE, (UINT32)1, (UINT8*)&data_exchange_spec); } if (result) { result &= SDP_AddAttribute(p_cb->sdp_handle, ATTR_ID_HDP_MCAP_SUP_PROC, UINT_DESC_TYPE, (UINT32)1, (UINT8*)&mcap_sup_proc); } if (result) { result &= SDP_AddUuidSequence(p_cb->sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, browse_list); } if (result) { for(i=0; i < num_services; i++) { bta_sys_add_uuid(svc_class_id_list[i]); APPL_TRACE_DEBUG2("dbg bta_sys_add_uuid i=%d uuid=0x%x", i, svc_class_id_list[i]); //todo } } else { if (p_cb->sdp_handle) { SDP_DeleteRecord(p_cb->sdp_handle); p_cb->sdp_handle = 0; } status = BTA_HL_STATUS_SDP_FAIL; } #if BTA_HL_DEBUG == TRUE APPL_TRACE_DEBUG1("bta_hl_sdp_register status=%s", bta_hl_status_code(status)); #endif return status; }
/******************************************************************************* ** ** 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; }