move esco accept connection to the upper layers (hfp, hsp)

This commit is contained in:
Milanka Ringwald 2016-07-28 11:41:57 +02:00
parent a33eb0c45b
commit 011577ab36
6 changed files with 77 additions and 52 deletions

View File

@ -518,6 +518,15 @@ void hfp_handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *packet
log_info("AG packet_handler type %u, event type %x, size %u", packet_type, hci_event_packet_get_type(packet), size); log_info("AG packet_handler type %u, event type %x, size %u", packet_type, hci_event_packet_get_type(packet), size);
switch (hci_event_packet_get_type(packet)) { switch (hci_event_packet_get_type(packet)) {
case HCI_EVENT_CONNECTION_REQUEST:
// printf("hfp HCI_EVENT_CONNECTION_REQUEST\n");
hci_event_connection_request_get_bd_addr(packet, event_addr);
hfp_connection = provide_hfp_connection_context_for_bd_addr(event_addr);
if (!hfp_connection) break;
hfp_connection->ag_establish_eSCO = 1;
break;
case RFCOMM_EVENT_INCOMING_CONNECTION: case RFCOMM_EVENT_INCOMING_CONNECTION:
// data: event (8), len(8), address(48), channel (8), rfcomm_cid (16) // data: event (8), len(8), address(48), channel (8), rfcomm_cid (16)
@ -575,30 +584,27 @@ void hfp_handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *packet
break; break;
case HCI_EVENT_SYNCHRONOUS_CONNECTION_COMPLETE:{ case HCI_EVENT_SYNCHRONOUS_CONNECTION_COMPLETE:{
hci_event_synchronous_connection_complete_get_bd_addr(packet, event_addr);
reverse_bd_addr(&packet[5], event_addr); hfp_connection = get_hfp_connection_context_for_bd_addr(event_addr);
int index = 2; if (!hfp_connection) {
status = packet[index++]; log_error("HFP: connection does not exist for remote with addr %s.", bd_addr_to_str(event_addr));
return;
}
hfp_connection->ag_establish_eSCO = 0;
status = hci_event_synchronous_connection_complete_get_status(packet);
if (status != 0){ if (status != 0){
hfp_handle_failed_sco_connection(status); hfp_handle_failed_sco_connection(status);
break; break;
} }
uint16_t sco_handle = little_endian_read_16(packet, index); uint16_t sco_handle = hci_event_synchronous_connection_complete_get_handle(packet);
index+=2; uint8_t link_type = hci_event_synchronous_connection_complete_get_link_type(packet);
uint8_t transmission_interval = hci_event_synchronous_connection_complete_get_transmission_interval(packet); // measured in slots
reverse_bd_addr(&packet[index], event_addr); uint8_t retransmission_interval = hci_event_synchronous_connection_complete_get_retransmission_interval(packet);// measured in slots
index+=6; uint16_t rx_packet_length = hci_event_synchronous_connection_complete_get_rx_packet_length(packet); // measured in bytes
uint16_t tx_packet_length = hci_event_synchronous_connection_complete_get_tx_packet_length(packet); // measured in bytes
uint8_t link_type = packet[index++]; uint8_t air_mode = hci_event_synchronous_connection_complete_get_air_mode(packet);
uint8_t transmission_interval = packet[index++]; // measured in slots
uint8_t retransmission_interval = packet[index++];// measured in slots
uint16_t rx_packet_length = little_endian_read_16(packet, index); // measured in bytes
index+=2;
uint16_t tx_packet_length = little_endian_read_16(packet, index); // measured in bytes
index+=2;
uint8_t air_mode = packet[index];
switch (link_type){ switch (link_type){
case 0x00: case 0x00:

View File

@ -561,6 +561,7 @@ typedef struct hfp_connection {
uint8_t send_response_and_hold_status; // 0 - don't send. BRTH:0 == 1, .. uint8_t send_response_and_hold_status; // 0 - don't send. BRTH:0 == 1, ..
// AG only // AG only
uint8_t ag_establish_eSCO;
uint8_t change_in_band_ring_tone_setting; uint8_t change_in_band_ring_tone_setting;
uint8_t ag_ring; uint8_t ag_ring;
uint8_t ag_send_clip; uint8_t ag_send_clip;

View File

@ -1626,6 +1626,23 @@ static void hfp_run_for_context(hfp_connection_t *hfp_connection){
if (!hfp_connection->rfcomm_cid) return; if (!hfp_connection->rfcomm_cid) return;
if (hfp_connection->ag_establish_eSCO && hci_can_send_command_packet_now()){
// remote supported feature eSCO is set if link type is eSCO
// eSCO: S4 - max latency == transmission interval = 0x000c == 12 ms,
uint16_t max_latency = 0x000c;
uint8_t retransmission_effort = 0x02;
uint16_t packet_types = 0x388;
uint16_t sco_voice_setting = hci_get_sco_voice_setting();
if (hfp_connection->negotiated_codec == HFP_CODEC_MSBC){
sco_voice_setting = 0x0003; // Transparent data
}
log_info("HFP: sending hci_accept_connection_request, sco_voice_setting %02x", sco_voice_setting);
hci_send_cmd(&hci_accept_synchronous_connection, hfp_connection->remote_addr, 8000, 8000, max_latency,
sco_voice_setting, retransmission_effort, packet_types);
return;
}
if (!rfcomm_can_send_packet_now(hfp_connection->rfcomm_cid)) { if (!rfcomm_can_send_packet_now(hfp_connection->rfcomm_cid)) {
log_info("hfp_run_for_context: request can send for 0x%02x", hfp_connection->rfcomm_cid); log_info("hfp_run_for_context: request can send for 0x%02x", hfp_connection->rfcomm_cid);
rfcomm_request_can_send_now_event(hfp_connection->rfcomm_cid); rfcomm_request_can_send_now_event(hfp_connection->rfcomm_cid);

View File

@ -76,6 +76,7 @@
static const char default_hsp_ag_service_name[] = "Audio Gateway"; static const char default_hsp_ag_service_name[] = "Audio Gateway";
static bd_addr_t remote; static bd_addr_t remote;
static bd_addr_t sco_event_addr;
static uint8_t channel_nr = 0; static uint8_t channel_nr = 0;
static uint16_t mtu; static uint16_t mtu;
@ -91,7 +92,7 @@ static uint8_t ag_send_ok = 0;
static uint8_t ag_send_error = 0; static uint8_t ag_send_error = 0;
static uint8_t ag_num_button_press_received = 0; static uint8_t ag_num_button_press_received = 0;
static uint8_t ag_support_custom_commands = 0; static uint8_t ag_support_custom_commands = 0;
static uint8_t ag_establish_eSCO = 0;
static uint8_t hsp_disconnect_rfcomm = 0; static uint8_t hsp_disconnect_rfcomm = 0;
static uint8_t hsp_establish_audio_connection = 0; static uint8_t hsp_establish_audio_connection = 0;
static uint8_t hsp_release_audio_connection = 0; static uint8_t hsp_release_audio_connection = 0;
@ -380,6 +381,11 @@ void hsp_ag_stop_ringing(void){
} }
static void hsp_run(void){ static void hsp_run(void){
if (ag_establish_eSCO && hci_can_send_command_packet_now()){
log_info("HSP: sending hci_accept_connection_request.");
hci_send_cmd(&hci_accept_synchronous_connection, sco_event_addr, 8000, 8000, 0xFFFF, hci_get_sco_voice_setting(), 0xFF, 0x003F);
return;
}
if (ag_send_ok){ if (ag_send_ok){
if (!rfcomm_can_send_packet_now(rfcomm_cid)) { if (!rfcomm_can_send_packet_now(rfcomm_cid)) {
@ -557,28 +563,29 @@ static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *pack
uint16_t handle; uint16_t handle;
switch (event) { switch (event) {
case HCI_EVENT_CONNECTION_REQUEST:
printf("hsp HCI_EVENT_CONNECTION_REQUEST\n");
hci_event_connection_request_get_bd_addr(packet, sco_event_addr);
ag_establish_eSCO = 1;
break;
case HCI_EVENT_SYNCHRONOUS_CONNECTION_COMPLETE:{ case HCI_EVENT_SYNCHRONOUS_CONNECTION_COMPLETE:{
int index = 2; ag_establish_eSCO = 0;
uint8_t status = packet[index++]; uint8_t status = hci_event_synchronous_connection_complete_get_status(packet);
sco_handle = little_endian_read_16(packet, index);
index+=2;
bd_addr_t address;
memcpy(address, &packet[index], 6);
index+=6;
uint8_t link_type = packet[index++];
uint8_t transmission_interval = packet[index++]; // measured in slots
uint8_t retransmission_interval = packet[index++];// measured in slots
uint16_t rx_packet_length = little_endian_read_16(packet, index); // measured in bytes
index+=2;
uint16_t tx_packet_length = little_endian_read_16(packet, index); // measured in bytes
index+=2;
uint8_t air_mode = packet[index];
if (status != 0){ if (status != 0){
log_error("(e)SCO Connection failed, status %u", status); log_error("(e)SCO Connection failed, status %u", status);
emit_event_audio_connected(status, sco_handle); emit_event_audio_connected(status, sco_handle);
break; break;
} }
hci_event_synchronous_connection_complete_get_bd_addr(packet, event_addr);
sco_handle = hci_event_synchronous_connection_complete_get_handle(packet);
uint8_t link_type = hci_event_synchronous_connection_complete_get_link_type(packet);
uint8_t transmission_interval = hci_event_synchronous_connection_complete_get_transmission_interval(packet); // measured in slots
uint8_t retransmission_interval = hci_event_synchronous_connection_complete_get_retransmission_interval(packet);// measured in slots
uint16_t rx_packet_length = hci_event_synchronous_connection_complete_get_rx_packet_length(packet); // measured in bytes
uint16_t tx_packet_length = hci_event_synchronous_connection_complete_get_tx_packet_length(packet); // measured in bytes
uint8_t air_mode = hci_event_synchronous_connection_complete_get_air_mode(packet);
switch (link_type){ switch (link_type){
case 0x00: case 0x00:
log_info("SCO Connection established."); log_info("SCO Connection established.");
@ -596,7 +603,7 @@ static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *pack
} }
log_info("sco_handle 0x%2x, address %s, transmission_interval %u slots, retransmission_interval %u slots, " log_info("sco_handle 0x%2x, address %s, transmission_interval %u slots, retransmission_interval %u slots, "
" rx_packet_length %u bytes, tx_packet_length %u bytes, air_mode 0x%2x (0x02 == CVSD)", sco_handle, " rx_packet_length %u bytes, tx_packet_length %u bytes, air_mode 0x%2x (0x02 == CVSD)", sco_handle,
bd_addr_to_str(address), transmission_interval, retransmission_interval, rx_packet_length, tx_packet_length, air_mode); bd_addr_to_str(event_addr), transmission_interval, retransmission_interval, rx_packet_length, tx_packet_length, air_mode);
if (hsp_state == HSP_W4_CONNECTION_ESTABLISHED_TO_SHUTDOWN){ if (hsp_state == HSP_W4_CONNECTION_ESTABLISHED_TO_SHUTDOWN){
hsp_state = HSP_W2_DISCONNECT_SCO; hsp_state = HSP_W2_DISCONNECT_SCO;

View File

@ -2544,21 +2544,11 @@ static void hci_run(void){
hci_send_cmd(&hci_accept_connection_request, connection->address, 1); hci_send_cmd(&hci_accept_connection_request, connection->address, 1);
} else { } else {
// remote supported feature eSCO is set if link type is eSCO // remote supported feature eSCO is set if link type is eSCO
uint16_t max_latency; if (connection->remote_supported_feature_eSCO) return;
uint8_t retransmission_effort; // SCO: max latency, retransmission interval: N/A. any packet type
uint16_t packet_types; uint16_t max_latency = 0xffff;
// remote supported feature eSCO is set if link type is eSCO uint8_t retransmission_effort = 0xff;
if (connection->remote_supported_feature_eSCO){ uint16_t packet_types = 0x003f;
// eSCO: S4 - max latency == transmission interval = 0x000c == 12 ms,
max_latency = 0x000c;
retransmission_effort = 0x02;
packet_types = 0x388;
} else {
// SCO: max latency, retransmission interval: N/A. any packet type
max_latency = 0xffff;
retransmission_effort = 0xff;
packet_types = 0x003f;
}
hci_send_cmd(&hci_accept_synchronous_connection, connection->address, 8000, 8000, max_latency, hci_stack->sco_voice_setting, retransmission_effort, packet_types); hci_send_cmd(&hci_accept_synchronous_connection, connection->address, 8000, 8000, max_latency, hci_stack->sco_voice_setting, retransmission_effort, packet_types);
} }
return; return;

View File

@ -212,6 +212,10 @@ int hci_send_cmd(const hci_cmd_t *cmd, ...){
return 0; return 0;
} }
int hci_can_send_command_packet_now(void){
return 1;
}
static void sdp_query_complete_response(uint8_t status){ static void sdp_query_complete_response(uint8_t status){
uint8_t event[3]; uint8_t event[3];
event[0] = SDP_EVENT_QUERY_COMPLETE; event[0] = SDP_EVENT_QUERY_COMPLETE;