static void hsp_run(void){ if (wait_ok) return; if (hs_accept_sco_connection && hci_can_send_command_packet_now()){ hs_accept_sco_connection = 0; log_info("HSP: sending hci_accept_connection_request."); // remote supported feature eSCO is set if link type is eSCO // eSCO: S4 - max latency == transmission interval = 0x000c == 12 ms, uint16_t max_latency; uint8_t retransmission_effort; uint16_t packet_types; if (hci_remote_esco_supported(rfcomm_handle)){ max_latency = 0x000c; retransmission_effort = 0x02; packet_types = 0x388; } else { max_latency = 0xffff; retransmission_effort = 0xff; packet_types = 0x003f; } uint16_t sco_voice_setting = hci_get_sco_voice_setting(); log_info("HFP: sending hci_accept_connection_request, sco_voice_setting %02x", sco_voice_setting); hci_send_cmd(&hci_accept_synchronous_connection, remote, 8000, 8000, max_latency, sco_voice_setting, retransmission_effort, packet_types); return; } if (hsp_release_audio_connection){ if (!rfcomm_can_send_packet_now(rfcomm_cid)) { rfcomm_request_can_send_now_event(rfcomm_cid); return; } hsp_release_audio_connection = 0; wait_ok = 1; hsp_hs_send_str_over_rfcomm(rfcomm_cid, HSP_HS_AT_CKPD); return; } if (hsp_disconnect_rfcomm){ hsp_disconnect_rfcomm = 0; hsp_establish_audio_connection = 0; rfcomm_disconnect(rfcomm_cid); return; } if (hsp_establish_audio_connection){ if (!rfcomm_can_send_packet_now(rfcomm_cid)) { rfcomm_request_can_send_now_event(rfcomm_cid); return; } hsp_establish_audio_connection = 0; wait_ok = 1; hsp_hs_send_str_over_rfcomm(rfcomm_cid, HSP_HS_AT_CKPD); return; } if (hs_send_button_press){ if (!rfcomm_can_send_packet_now(rfcomm_cid)) { rfcomm_request_can_send_now_event(rfcomm_cid); return; } hs_send_button_press = 0; wait_ok = 1; hsp_hs_send_str_over_rfcomm(rfcomm_cid, HSP_HS_AT_CKPD); return; } switch (hsp_state){ case HSP_SDP_QUERY_RFCOMM_CHANNEL: hsp_state = HSP_W4_SDP_QUERY_COMPLETE; sdp_client_query_rfcomm_channel_and_name_for_uuid(&handle_query_rfcomm_event, remote, BLUETOOTH_SERVICE_CLASS_HEADSET_AUDIO_GATEWAY_AG); break; case HSP_AUDIO_CONNECTION_ESTABLISHED: case HSP_RFCOMM_CONNECTION_ESTABLISHED: if (hs_microphone_gain >= 0){ if (!rfcomm_can_send_packet_now(rfcomm_cid)) { rfcomm_request_can_send_now_event(rfcomm_cid); return; } char buffer[20]; sprintf(buffer, "%s=%d\r\n", HSP_HS_MICROPHONE_GAIN, hs_microphone_gain); hsp_hs_send_str_over_rfcomm(rfcomm_cid, buffer); hs_microphone_gain = -1; break; } if (hs_speaker_gain >= 0){ if (!rfcomm_can_send_packet_now(rfcomm_cid)) { rfcomm_request_can_send_now_event(rfcomm_cid); return; } char buffer[20]; sprintf(buffer, "%s=%d\r\n", HSP_HS_SPEAKER_GAIN, hs_speaker_gain); hsp_hs_send_str_over_rfcomm(rfcomm_cid, buffer); hs_speaker_gain = -1; break; } break; case HSP_W4_RFCOMM_DISCONNECTED: rfcomm_disconnect(rfcomm_cid); break; default: break; } }
static void hsp_run(void){ int err; if (ag_send_ok){ ag_send_ok = 0; err = hsp_ag_send_str_over_rfcomm(rfcomm_cid, HSP_AG_OK); if (err){ ag_send_ok = 1; } return; } if (ag_send_error){ ag_send_error = 0; err = hsp_ag_send_str_over_rfcomm(rfcomm_cid, HSP_AG_ERROR); if (err) { ag_send_error = 1; } return; } switch (hsp_state){ case HSP_SDP_QUERY_RFCOMM_CHANNEL: hsp_state = HSP_W4_SDP_QUERY_COMPLETE; log_info("Start SDP query %s, 0x%02x", bd_addr_to_str(remote), SDP_HSP); sdp_query_rfcomm_channel_and_name_for_uuid(remote, SDP_HSP); break; case HSP_W4_RING_ANSWER: if (ag_ring){ ag_ring = 0; err = hsp_ag_send_str_over_rfcomm(rfcomm_cid, HSP_AG_RING); if (err) { ag_ring = 1; } break; } if (!ag_num_button_press_received) break; ag_send_ok = 0; ag_num_button_press_received = 0; hsp_state = HSP_W2_CONNECT_SCO; err = hsp_ag_send_str_over_rfcomm(rfcomm_cid, HSP_AG_OK); if (err) { hsp_state = HSP_W4_RING_ANSWER; ag_num_button_press_received = 1; } break; case HSP_W2_CONNECT_SCO: if (!hci_can_send_command_packet_now()) break; hsp_state = HSP_W4_SCO_CONNECTED; hci_send_cmd(&hci_setup_synchronous_connection, rfcomm_handle, 8000, 8000, 0xFFFF, hci_get_sco_voice_setting(), 0xFF, 0x003F); break; case HSP_W2_DISCONNECT_SCO: ag_num_button_press_received = 0; hsp_state = HSP_W4_SCO_DISCONNECTED; gap_disconnect(sco_handle); break; case HSP_W2_DISCONNECT_RFCOMM: hsp_state = HSP_W4_RFCOMM_DISCONNECTED; rfcomm_disconnect_internal(rfcomm_cid); break; case HSP_ACTIVE: if (ag_microphone_gain >= 0){ int gain = ag_microphone_gain; ag_microphone_gain = -1; char buffer[10]; sprintf(buffer, "%s=%d\r\n", HSP_MICROPHONE_GAIN, gain); err = hsp_ag_send_str_over_rfcomm(rfcomm_cid, buffer); if (err) { ag_microphone_gain = gain; } break; } if (ag_speaker_gain >= 0){ int gain = ag_speaker_gain; ag_speaker_gain = -1; char buffer[10]; sprintf(buffer, "%s=%d\r\n", HSP_SPEAKER_GAIN, gain); err = hsp_ag_send_str_over_rfcomm(rfcomm_cid, buffer); if (err) { ag_speaker_gain = gain; } break; } break; default: break; } }
static int hfp_ag_run_for_audio_connection(hfp_connection_t * context){ if (context->state < HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED || context->state > HFP_W2_DISCONNECT_SCO) return 0; if (context->state == HFP_AUDIO_CONNECTION_ESTABLISHED && context->release_audio_connection){ context->state = HFP_W4_SCO_DISCONNECTED; context->release_audio_connection = 0; gap_disconnect(context->sco_handle); return 1; } if (context->state == HFP_AUDIO_CONNECTION_ESTABLISHED) return 0; // run codecs exchange int done = codecs_exchange_state_machine(context); if (done) return done; // printf(" -> State machine: Audio Connection\n"); if (context->codecs_state != HFP_CODECS_EXCHANGED) return done; if (context->establish_audio_connection){ context->state = HFP_W4_SCO_CONNECTED; context->establish_audio_connection = 0; hci_send_cmd(&hci_setup_synchronous_connection, context->con_handle, 8000, 8000, 0xFFFF, hci_get_sco_voice_setting(), 0xFF, 0x003F); return 1; } return 0; }