/******************************************************************************* ** ** Function bta_pan_sm_execute ** ** Description State machine event handling function for PAN ** ** ** Returns void ** *******************************************************************************/ static void bta_pan_sm_execute(tBTA_PAN_SCB *p_scb, UINT16 event, tBTA_PAN_DATA *p_data) { tBTA_PAN_ST_TBL state_table; UINT8 action; int i; APPL_TRACE_EVENT("PAN scb=%d event=0x%x state=%d", bta_pan_scb_to_idx(p_scb), event, p_scb->state); /* look up the state table for the current state */ state_table = bta_pan_st_tbl[p_scb->state]; event &= 0x00FF; /* set next state */ p_scb->state = state_table[event][BTA_PAN_NEXT_STATE]; /* execute action functions */ for (i = 0; i < BTA_PAN_ACTIONS; i++) { if ((action = state_table[event][i]) != BTA_PAN_IGNORE) { (*bta_pan_action[action])(p_scb, p_data); } else { break; } } }
/******************************************************************************* ** ** Function bta_dm_search_sm_execute ** ** Description State machine event handling function for DM ** ** ** Returns void ** *******************************************************************************/ BOOLEAN bta_dm_search_sm_execute(BT_HDR *p_msg) { tBTA_DM_ST_TBL state_table; UINT8 action; int i; APPL_TRACE_EVENT("bta_dm_search_sm_execute state:%d, event:0x%x", bta_dm_search_cb.state, p_msg->event); #if BTA_GATT_INCLUDED == TRUE if ((bta_dm_search_cb.state == BTA_DM_SEARCH_IDLE) && ((p_msg->event == BTA_DM_API_SEARCH_EVT) || (p_msg->event == BTA_DM_API_DISCOVER_EVT))) { bta_dm_gattc_service_search_close(p_msg->event); } #endif /* look up the state table for the current state */ state_table = bta_dm_search_st_tbl[bta_dm_search_cb.state]; bta_dm_search_cb.state = state_table[p_msg->event & 0x00ff][BTA_DM_SEARCH_NEXT_STATE]; /* execute action functions */ for (i = 0; i < BTA_DM_SEARCH_ACTIONS; i++) { if ((action = state_table[p_msg->event & 0x00ff][i]) < BTA_DM_SEARCH_IGNORE) { (*bta_dm_search_action[action])( (tBTA_DM_MSG*) p_msg); } else { break; } } return TRUE; }
/******************************************************************************* ** ** Function bta_hh_di_sdp_cback ** ** Description SDP DI callback function. ** ** Returns void ** *******************************************************************************/ static void bta_hh_di_sdp_cback(UINT16 result) { tBTA_HH_DEV_CB *p_cb = bta_hh_cb.p_cur; tBTA_HH_STATUS status = BTA_HH_ERR_SDP; tSDP_DI_GET_RECORD di_rec; tHID_STATUS ret; #if BTA_HH_DEBUG APPL_TRACE_EVENT("bta_hh_di_sdp_cback: p_cb: %d result 0x%02x", p_cb, result); #endif /* if DI record does not exist on remote device, vendor_id in tBTA_HH_DEV_DSCP_INFO will be * set to 0xffff and we will allow the connection to go through. Spec mandates that DI * record be set, but many HID devices do not set this. So for IOP purposes, we allow the * connection to go through and update the DI record to invalid DI entry.*/ if (((result == SDP_SUCCESS) || (result == SDP_NO_RECS_MATCH)) && (p_cb != NULL)) { if(result == SDP_SUCCESS && SDP_GetNumDiRecords(bta_hh_cb.p_disc_db) != 0) { /* always update information with primary DI record */ if (SDP_GetDiRecord(1, &di_rec, bta_hh_cb.p_disc_db) == SDP_SUCCESS) { bta_hh_update_di_info(p_cb, di_rec.rec.vendor, di_rec.rec.product, di_rec.rec.version, 0); } } else /* no DI recrod available */ { bta_hh_update_di_info(p_cb, BTA_HH_VENDOR_ID_INVALID, 0, 0, 0); } if ((ret = HID_HostGetSDPRecord(p_cb->addr, bta_hh_cb.p_disc_db, p_bta_hh_cfg->sdp_db_size, bta_hh_sdp_cback)) == HID_SUCCESS) { status = BTA_HH_OK; } else { #if BTA_HH_DEBUG APPL_TRACE_DEBUG ("bta_hh_di_sdp_cback: HID_HostGetSDPRecord failed: Status 0x%2x", ret); #endif } } if (status != BTA_HH_OK) { utl_freebuf((void **)&bta_hh_cb.p_disc_db); /* send SDP_CMPL_EVT into state machine */ bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, (tBTA_HH_DATA *)&status); } return; }
static void btc_a2dp_sink_thread_init(UNUSED_ATTR void *context) { APPL_TRACE_EVENT("%s\n", __func__); memset(&btc_aa_snk_cb, 0, sizeof(btc_aa_snk_cb)); btc_a2dp_sink_state = BTC_A2DP_SINK_STATE_ON; btc_aa_snk_cb.RxSbcQ = fixed_queue_new(SIZE_MAX); btc_a2dp_control_init(); }
/******************************************************************************* ** ** Function bta_dm_sm_execute ** ** Description State machine event handling function for DM ** ** ** Returns void ** *******************************************************************************/ BOOLEAN bta_dm_sm_execute(BT_HDR *p_msg) { UINT16 event = p_msg->event & 0x00ff; APPL_TRACE_EVENT("bta_dm_sm_execute event:0x%x", event); /* execute action functions */ if(event < BTA_DM_NUM_ACTIONS) { (*bta_dm_action[event])( (tBTA_DM_MSG*) p_msg); } return TRUE; }
void btc_a2dp_sink_reset_decoder(UINT8 *p_av) { APPL_TRACE_EVENT("btc reset decoder"); APPL_TRACE_DEBUG("btc reset decoder p_codec_info[%x:%x:%x:%x:%x:%x]\n", p_av[1], p_av[2], p_av[3], p_av[4], p_av[5], p_av[6]); tBTC_MEDIA_SINK_CFG_UPDATE *p_buf; if (NULL == (p_buf = osi_malloc(sizeof(tBTC_MEDIA_SINK_CFG_UPDATE)))) { APPL_TRACE_ERROR("btc reset decoder No Buffer "); return; } memcpy(p_buf->codec_info, p_av, AVDT_CODEC_SIZE); btc_a2dp_sink_ctrl_post(BTC_MEDIA_AUDIO_SINK_CFG_UPDATE, p_buf); }
void btc_a2dp_sink_shutdown(void) { APPL_TRACE_EVENT("## A2DP SINK STOP MEDIA THREAD ##\n"); // Exit thread btc_a2dp_sink_ctrl_post(BTC_MEDIA_TASK_SINK_CLEAN_UP, NULL); vTaskDelete(btc_aa_snk_task_hdl); btc_aa_snk_task_hdl = NULL; vQueueDelete(btc_aa_snk_data_queue); btc_aa_snk_data_queue = NULL; vQueueDelete(btc_aa_snk_ctrl_queue); btc_aa_snk_ctrl_queue = NULL; }
/******************************************************************************* ** ** Function bta_hh_sdp_cback ** ** Description SDP callback function. ** ** Returns void ** *******************************************************************************/ static void bta_hh_sdp_cback(UINT16 result, UINT16 attr_mask, tHID_DEV_SDP_INFO *sdp_rec ) { tBTA_HH_DEV_CB *p_cb = bta_hh_cb.p_cur; UINT8 hdl = 0; tBTA_HH_STATUS status = BTA_HH_ERR_SDP; /* make sure sdp succeeded and hh has not been disabled */ if ((result == SDP_SUCCESS) && (p_cb != NULL)) { /* security is required for the connection, add attr_mask bit*/ if (p_cb->sec_mask) attr_mask |= HID_SEC_REQUIRED; #if BTA_HH_DEBUG APPL_TRACE_EVENT("bta_hh_sdp_cback: p_cb: %d result 0x%02x, \ attr_mask 0x%02x, handle %x", \ p_cb, result, attr_mask,p_cb->hid_handle); #endif /* check to see type of device is supported , and should not been added before */ if (bta_hh_tod_spt(p_cb, sdp_rec->sub_class)) { /* if not added before */ if (p_cb->hid_handle == BTA_HH_INVALID_HANDLE) { /* add device/update attr_mask information */ if(HID_HostAddDev (p_cb->addr, attr_mask, &hdl) == HID_SUCCESS) { status = BTA_HH_OK; /* update cb_index[] map */ bta_hh_cb.cb_index[hdl] = p_cb->index; } else { p_cb->app_id = 0; } } else { hdl = p_cb->hid_handle; } /* else : incoming connection after SDP should update the SDP information as well */ if (p_cb->app_id != 0) { /* update cb information with attr_mask, dscp_info etc. */ bta_hh_add_device_to_list(p_cb, hdl, attr_mask, &sdp_rec->dscp_info, sdp_rec->sub_class, sdp_rec->ssr_max_latency, sdp_rec->ssr_min_tout, p_cb->app_id); p_cb->dscp_info.ctry_code = sdp_rec->ctry_code; status = BTA_HH_OK; } } else /* type of device is not supported */ status = BTA_HH_ERR_TOD_UNSPT; } /* free disc_db when SDP is completed */ utl_freebuf((void **)&bta_hh_cb.p_disc_db); /* send SDP_CMPL_EVT into state machine */ bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, (tBTA_HH_DATA *)&status); return; }
/******************************************************************************* ** ** Function bta_av_ssm_execute ** ** Description Stream state machine event handling function for AV ** ** ** Returns void ** *******************************************************************************/ void bta_av_ssm_execute(tBTA_AV_SCB *p_scb, UINT16 event, tBTA_AV_DATA *p_data) { tBTA_AV_SST_TBL state_table; UINT8 action; int i, xx; if(p_scb == NULL) { /* this stream is not registered */ APPL_TRACE_EVENT("AV channel not registered"); return; } /* In case incoming connection is for VDP, we need to swap scb. */ /* When ACP_CONNECT_EVT was received, we put first available scb to */ /* to Incoming state. Later, when STR_CONFIG_IND_EVT is coming, we */ /* know if it is A2DP or VDP. */ if ((p_scb->state == BTA_AV_INIT_SST) && (event == BTA_AV_STR_CONFIG_IND_EVT)) { for (xx = 0; xx < BTA_AV_NUM_STRS; xx++) { if (bta_av_cb.p_scb[xx]) { if (bta_av_cb.p_scb[xx]->state == BTA_AV_INCOMING_SST) { bta_av_cb.p_scb[xx]->state = BTA_AV_INIT_SST; bta_av_cb.p_scb[xx]->coll_mask = 0; p_scb->state = BTA_AV_INCOMING_SST; break; } } } } if ((event != BTA_AV_STR_WRITE_CFM_EVT) && (event != BTA_AV_SRC_DATA_READY_EVT)) { #if (defined(BTA_AV_DEBUG) && BTA_AV_DEBUG == TRUE) APPL_TRACE_IMP("AV Sevent(0x%x)=0x%x(%s) state=%d(%s)", p_scb->hndl, event, bta_av_evt_code(event), p_scb->state, bta_av_sst_code(p_scb->state)); #else APPL_TRACE_IMP("AV Sevent=0x%x state=%d", event, p_scb->state); #endif } /* look up the state table for the current state */ state_table = bta_av_sst_tbl[p_scb->state]; event -= BTA_AV_FIRST_SSM_EVT; /* set next state */ p_scb->state = state_table[event][BTA_AV_SNEXT_STATE]; /* execute action functions */ for(i=0; i< BTA_AV_SACTIONS; i++) { if ((action = state_table[event][i]) != BTA_AV_SIGNORE) { (*p_scb->p_act_tbl[action])(p_scb, p_data); } else break; } }
/******************************************************************************* ** ** Function bta_hh_sm_execute ** ** Description State machine event handling function for HID Host ** ** ** Returns void ** *******************************************************************************/ void bta_hh_sm_execute(tBTA_HH_DEV_CB *p_cb, UINT16 event, tBTA_HH_DATA *p_data) { tBTA_HH_ST_TBL state_table; UINT8 action; tBTA_HH cback_data; tBTA_HH_EVT cback_event = 0; #if BTA_HH_DEBUG == TRUE tBTA_HH_STATE in_state ; UINT16 debug_event = event; #endif memset(&cback_data, 0, sizeof(tBTA_HH)); /* handle exception, no valid control block was found */ if (!p_cb) { /* BTA HH enabled already? otherwise ignore the event although it's bad*/ if (bta_hh_cb.p_cback != NULL) { switch (event) { /* no control block available for new connection */ case BTA_HH_API_OPEN_EVT: cback_event = BTA_HH_OPEN_EVT; /* build cback data */ bdcpy(cback_data.conn.bda, ((tBTA_HH_API_CONN *)p_data)->bd_addr); cback_data.conn.status = BTA_HH_ERR_DB_FULL; cback_data.conn.handle = BTA_HH_INVALID_HANDLE; break; /* DB full, BTA_HhAddDev */ case BTA_HH_API_MAINT_DEV_EVT: cback_event = p_data->api_maintdev.sub_event; if (p_data->api_maintdev.sub_event == BTA_HH_ADD_DEV_EVT) { bdcpy(cback_data.dev_info.bda, p_data->api_maintdev.bda); cback_data.dev_info.status = BTA_HH_ERR_DB_FULL; cback_data.dev_info.handle = BTA_HH_INVALID_HANDLE; } else { cback_data.dev_info.status = BTA_HH_ERR_HDL; cback_data.dev_info.handle = (UINT8)p_data->api_maintdev.hdr.layer_specific; } break; case BTA_HH_API_WRITE_DEV_EVT: cback_event = (p_data->api_sndcmd.t_type - BTA_HH_FST_BTE_TRANS_EVT) + BTA_HH_FST_TRANS_CB_EVT; if (p_data->api_sndcmd.p_data != NULL) { osi_free(p_data->api_sndcmd.p_data); } if (p_data->api_sndcmd.t_type == HID_TRANS_SET_PROTOCOL || p_data->api_sndcmd.t_type == HID_TRANS_SET_REPORT || p_data->api_sndcmd.t_type == HID_TRANS_SET_IDLE) { cback_data.dev_status.status = BTA_HH_ERR_HDL; cback_data.dev_status.handle = (UINT8)p_data->api_sndcmd.hdr.layer_specific; } else if (p_data->api_sndcmd.t_type != HID_TRANS_DATA && p_data->api_sndcmd.t_type != HID_TRANS_CONTROL) { cback_data.hs_data.handle = (UINT8)p_data->api_sndcmd.hdr.layer_specific; cback_data.hs_data.status = BTA_HH_ERR_HDL; /* hs_data.rsp_data will be all zero, which is not valid value */ } else if (p_data->api_sndcmd.t_type == HID_TRANS_CONTROL && p_data->api_sndcmd.param == BTA_HH_CTRL_VIRTUAL_CABLE_UNPLUG) { cback_data.status = BTA_HH_ERR_HDL; cback_event = BTA_HH_VC_UNPLUG_EVT; } else { cback_event = 0; } break; case BTA_HH_API_CLOSE_EVT: cback_event = BTA_HH_CLOSE_EVT; cback_data.dev_status.status = BTA_HH_ERR_HDL; cback_data.dev_status.handle = (UINT8)p_data->api_sndcmd.hdr.layer_specific; break; default: /* invalid handle, call bad API event */ APPL_TRACE_ERROR("wrong device handle: [%d]", p_data->hdr.layer_specific); /* Free the callback buffer now */ if (p_data != NULL && p_data->hid_cback.p_data != NULL) { osi_free(p_data->hid_cback.p_data); p_data->hid_cback.p_data = NULL; } break; } if (cback_event) { (* bta_hh_cb.p_cback)(cback_event, &cback_data); } } } /* corresponding CB is found, go to state machine */ else { #if BTA_HH_DEBUG == TRUE in_state = p_cb->state; APPL_TRACE_EVENT("bta_hh_sm_execute: State 0x%02x [%s], Event [%s]", in_state, bta_hh_state_code(in_state), bta_hh_evt_code(debug_event)); #endif if ((p_cb->state == BTA_HH_NULL_ST) || (p_cb->state >= BTA_HH_INVALID_ST)) { APPL_TRACE_ERROR("bta_hh_sm_execute: Invalid state State = 0x%x, Event = %d", p_cb->state, event); return; } state_table = bta_hh_st_tbl[p_cb->state - 1]; event &= 0xff; p_cb->state = state_table[event][BTA_HH_NEXT_STATE] ; if ((action = state_table[event][BTA_HH_ACTION]) != BTA_HH_IGNORE) { (*bta_hh_action[action])(p_cb, p_data); } #if BTA_HH_DEBUG == TRUE if (in_state != p_cb->state) { APPL_TRACE_DEBUG("HH State Change: [%s] -> [%s] after Event [%s]", bta_hh_state_code(in_state), bta_hh_state_code(p_cb->state), bta_hh_evt_code(debug_event)); } #endif } return; }
/******************************************************************************* ** ** Function btc_a2dp_sink_handle_decoder_reset ** ** Description ** ** Returns void ** *******************************************************************************/ static void btc_a2dp_sink_handle_decoder_reset(tBTC_MEDIA_SINK_CFG_UPDATE *p_msg) { tBTC_MEDIA_SINK_CFG_UPDATE *p_buf = p_msg; tA2D_STATUS a2d_status; tA2D_SBC_CIE sbc_cie; OI_STATUS status; UINT32 freq_multiple = 48 * 20; /* frequency multiple for 20ms of data , initialize with 48K*/ UINT32 num_blocks = 16; UINT32 num_subbands = 8; APPL_TRACE_EVENT("%s p_codec_info[%x:%x:%x:%x:%x:%x]\n", __FUNCTION__, p_buf->codec_info[1], p_buf->codec_info[2], p_buf->codec_info[3], p_buf->codec_info[4], p_buf->codec_info[5], p_buf->codec_info[6]); a2d_status = A2D_ParsSbcInfo(&sbc_cie, p_buf->codec_info, FALSE); if (a2d_status != A2D_SUCCESS) { APPL_TRACE_ERROR("ERROR dump_codec_info A2D_ParsSbcInfo fail:%d\n", a2d_status); return; } btc_aa_snk_cb.sample_rate = btc_a2dp_sink_get_track_frequency(sbc_cie.samp_freq); btc_aa_snk_cb.channel_count = btc_a2dp_sink_get_track_channel_count(sbc_cie.ch_mode); btc_aa_snk_cb.rx_flush = FALSE; APPL_TRACE_EVENT("Reset to sink role"); status = OI_CODEC_SBC_DecoderReset(&context, contextData, sizeof(contextData), 2, 2, FALSE); if (!OI_SUCCESS(status)) { APPL_TRACE_ERROR("OI_CODEC_SBC_DecoderReset failed with error code %d\n", status); } btc_a2dp_control_set_datachnl_stat(TRUE); switch (sbc_cie.samp_freq) { case A2D_SBC_IE_SAMP_FREQ_16: APPL_TRACE_DEBUG("\tsamp_freq:%d (16000)\n", sbc_cie.samp_freq); freq_multiple = 16 * 20; break; case A2D_SBC_IE_SAMP_FREQ_32: APPL_TRACE_DEBUG("\tsamp_freq:%d (32000)\n", sbc_cie.samp_freq); freq_multiple = 32 * 20; break; case A2D_SBC_IE_SAMP_FREQ_44: APPL_TRACE_DEBUG("\tsamp_freq:%d (44100)\n", sbc_cie.samp_freq); freq_multiple = 441 * 2; break; case A2D_SBC_IE_SAMP_FREQ_48: APPL_TRACE_DEBUG("\tsamp_freq:%d (48000)\n", sbc_cie.samp_freq); freq_multiple = 48 * 20; break; default: APPL_TRACE_DEBUG(" Unknown Frequency "); break; } switch (sbc_cie.ch_mode) { case A2D_SBC_IE_CH_MD_MONO: APPL_TRACE_DEBUG("\tch_mode:%d (Mono)\n", sbc_cie.ch_mode); break; case A2D_SBC_IE_CH_MD_DUAL: APPL_TRACE_DEBUG("\tch_mode:%d (DUAL)\n", sbc_cie.ch_mode); break; case A2D_SBC_IE_CH_MD_STEREO: APPL_TRACE_DEBUG("\tch_mode:%d (STEREO)\n", sbc_cie.ch_mode); break; case A2D_SBC_IE_CH_MD_JOINT: APPL_TRACE_DEBUG("\tch_mode:%d (JOINT)\n", sbc_cie.ch_mode); break; default: APPL_TRACE_DEBUG(" Unknown Mode "); break; } switch (sbc_cie.block_len) { case A2D_SBC_IE_BLOCKS_4: APPL_TRACE_DEBUG("\tblock_len:%d (4)\n", sbc_cie.block_len); num_blocks = 4; break; case A2D_SBC_IE_BLOCKS_8: APPL_TRACE_DEBUG("\tblock_len:%d (8)\n", sbc_cie.block_len); num_blocks = 8; break; case A2D_SBC_IE_BLOCKS_12: APPL_TRACE_DEBUG("\tblock_len:%d (12)\n", sbc_cie.block_len); num_blocks = 12; break; case A2D_SBC_IE_BLOCKS_16: APPL_TRACE_DEBUG("\tblock_len:%d (16)\n", sbc_cie.block_len); num_blocks = 16; break; default: APPL_TRACE_DEBUG(" Unknown BlockLen "); break; } switch (sbc_cie.num_subbands) { case A2D_SBC_IE_SUBBAND_4: APPL_TRACE_DEBUG("\tnum_subbands:%d (4)\n", sbc_cie.num_subbands); num_subbands = 4; break; case A2D_SBC_IE_SUBBAND_8: APPL_TRACE_DEBUG("\tnum_subbands:%d (8)\n", sbc_cie.num_subbands); num_subbands = 8; break; default: APPL_TRACE_DEBUG(" Unknown SubBands "); break; } switch (sbc_cie.alloc_mthd) { case A2D_SBC_IE_ALLOC_MD_S: APPL_TRACE_DEBUG("\talloc_mthd:%d (SNR)\n", sbc_cie.alloc_mthd); break; case A2D_SBC_IE_ALLOC_MD_L: APPL_TRACE_DEBUG("\talloc_mthd:%d (Loudness)\n", sbc_cie.alloc_mthd); break; default: APPL_TRACE_DEBUG(" Unknown Allocation Method"); break; } APPL_TRACE_EVENT("\tBit pool Min:%d Max:%d\n", sbc_cie.min_bitpool, sbc_cie.max_bitpool); int frames_to_process = ((freq_multiple) / (num_blocks * num_subbands)) + 1; APPL_TRACE_EVENT(" Frames to be processed in 20 ms %d\n", frames_to_process); }
/* when true media task discards any rx frames */ void btc_a2dp_sink_set_rx_flush(BOOLEAN enable) { APPL_TRACE_EVENT("## DROP RX %d ##\n", enable); btc_aa_snk_cb.rx_flush = enable; }