diff --git a/src/classic/hfp.c b/src/classic/hfp.c index 3c28275bf..62a72ac5e 100644 --- a/src/classic/hfp.c +++ b/src/classic/hfp.c @@ -109,8 +109,6 @@ static btstack_packet_handler_t hfp_ag_rfcomm_packet_handler; static void (*hfp_hf_run_for_context)(hfp_connection_t * hfp_connection); -static btstack_packet_callback_registration_t hci_event_callback_registration; - static hfp_connection_t * sco_establishment_active; const char * hfp_hf_feature(int index){ @@ -564,15 +562,15 @@ static void hfp_handle_failed_sco_connection(uint8_t status){ } -void hfp_handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size, hfp_role_t local_role){ +void hfp_handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ UNUSED(channel); // ok: no channel bd_addr_t event_addr; - uint16_t rfcomm_cid, handle; + hci_con_handle_t handle; hfp_connection_t * hfp_connection = NULL; uint8_t status; - log_debug("HFP packet_handler type %u, event type %x, size %u", packet_type, hci_event_packet_get_type(packet), size); + log_debug("HFP HCI event handler type %u, event type %x, size %u", packet_type, hci_event_packet_get_type(packet), size); switch (hci_event_packet_get_type(packet)) { @@ -593,60 +591,6 @@ void hfp_handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *packet } break; - case RFCOMM_EVENT_INCOMING_CONNECTION: - // data: event (8), len(8), address(48), channel (8), rfcomm_cid (16) - rfcomm_event_incoming_connection_get_bd_addr(packet, event_addr); - hfp_connection = provide_hfp_connection_context_for_bd_addr(event_addr, local_role); - if (!hfp_connection){ - log_info("hfp: no memory to accept incoming connection - decline"); - rfcomm_decline_connection(rfcomm_event_incoming_connection_get_rfcomm_cid(packet)); - return; - } - if (hfp_connection->state != HFP_IDLE) { - log_error("hfp: incoming connection but state != HFP_IDLE"); - return; - } - - hfp_connection->rfcomm_cid = rfcomm_event_incoming_connection_get_rfcomm_cid(packet); - hfp_connection->state = HFP_W4_RFCOMM_CONNECTED; - // printf("RFCOMM channel %u requested for %s\n", hfp_connection->rfcomm_cid, bd_addr_to_str(hfp_connection->remote_addr)); - rfcomm_accept_connection(hfp_connection->rfcomm_cid); - break; - - case RFCOMM_EVENT_CHANNEL_OPENED: - // data: event(8), len(8), status (8), address (48), handle(16), server channel(8), rfcomm_cid(16), max frame size(16) - - rfcomm_event_channel_opened_get_bd_addr(packet, event_addr); - status = rfcomm_event_channel_opened_get_status(packet); - - hfp_connection = get_hfp_connection_context_for_bd_addr(event_addr); - if (!hfp_connection || hfp_connection->state != HFP_W4_RFCOMM_CONNECTED) return; - - if (status) { - hfp_emit_slc_connection_event(hfp_connection, status, rfcomm_event_channel_opened_get_con_handle(packet), event_addr); - remove_hfp_connection_context(hfp_connection); - } else { - hfp_connection->acl_handle = rfcomm_event_channel_opened_get_con_handle(packet); - hfp_connection->rfcomm_cid = rfcomm_event_channel_opened_get_rfcomm_cid(packet); - bd_addr_copy(hfp_connection->remote_addr, event_addr); - // uint16_t mtu = rfcomm_event_channel_opened_get_max_frame_size(packet); - // printf("RFCOMM channel open succeeded. hfp_connection %p, RFCOMM Channel ID 0x%02x, max frame size %u\n", hfp_connection, hfp_connection->rfcomm_cid, mtu); - - switch (hfp_connection->state){ - case HFP_W4_RFCOMM_CONNECTED: - hfp_connection->state = HFP_EXCHANGE_SUPPORTED_FEATURES; - break; - case HFP_W4_CONNECTION_ESTABLISHED_TO_SHUTDOWN: - hfp_connection->state = HFP_W2_DISCONNECT_RFCOMM; - // printf("Shutting down RFCOMM.\n"); - break; - default: - break; - } - rfcomm_request_can_send_now_event(hfp_connection->rfcomm_cid); - } - break; - case HCI_EVENT_COMMAND_STATUS: if (hci_event_command_status_get_command_opcode(packet) == hci_setup_synchronous_connection.opcode) { status = hci_event_command_status_get_status(packet); @@ -717,23 +661,6 @@ void hfp_handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *packet break; } - case RFCOMM_EVENT_CHANNEL_CLOSED: - if (local_role > 1){ - log_error("hfp_handle_hci_event role %x", local_role); - } - rfcomm_cid = little_endian_read_16(packet,2); - hfp_connection = get_hfp_connection_context_for_rfcomm_cid(rfcomm_cid); - if (!hfp_connection) break; - if (hfp_connection->state == HFP_W4_RFCOMM_DISCONNECTED_AND_RESTART){ - hfp_connection->state = HFP_IDLE; - hfp_establish_service_level_connection(hfp_connection->remote_addr, hfp_connection->service_uuid, local_role); - break; - } - - hfp_emit_event(hfp_connection, HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_RELEASED, 0); - remove_hfp_connection_context(hfp_connection); - break; - case HCI_EVENT_DISCONNECTION_COMPLETE: handle = little_endian_read_16(packet,3); hfp_connection = get_hfp_connection_context_for_sco_handle(handle); @@ -760,6 +687,90 @@ void hfp_handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *packet } } +void hfp_handle_rfcomm_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size, hfp_role_t local_role){ + UNUSED(channel); // ok: no channel + + bd_addr_t event_addr; + uint16_t rfcomm_cid; + hfp_connection_t * hfp_connection = NULL; + uint8_t status; + + log_debug("HFP 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)) { + + case RFCOMM_EVENT_INCOMING_CONNECTION: + // data: event (8), len(8), address(48), channel (8), rfcomm_cid (16) + rfcomm_event_incoming_connection_get_bd_addr(packet, event_addr); + hfp_connection = provide_hfp_connection_context_for_bd_addr(event_addr, local_role); + if (!hfp_connection){ + log_info("hfp: no memory to accept incoming connection - decline"); + rfcomm_decline_connection(rfcomm_event_incoming_connection_get_rfcomm_cid(packet)); + return; + } + if (hfp_connection->state != HFP_IDLE) { + log_error("hfp: incoming connection but state != HFP_IDLE"); + return; + } + + hfp_connection->rfcomm_cid = rfcomm_event_incoming_connection_get_rfcomm_cid(packet); + hfp_connection->state = HFP_W4_RFCOMM_CONNECTED; + // printf("RFCOMM channel %u requested for %s\n", hfp_connection->rfcomm_cid, bd_addr_to_str(hfp_connection->remote_addr)); + rfcomm_accept_connection(hfp_connection->rfcomm_cid); + break; + + case RFCOMM_EVENT_CHANNEL_OPENED: + // data: event(8), len(8), status (8), address (48), handle(16), server channel(8), rfcomm_cid(16), max frame size(16) + + rfcomm_event_channel_opened_get_bd_addr(packet, event_addr); + status = rfcomm_event_channel_opened_get_status(packet); + + hfp_connection = get_hfp_connection_context_for_bd_addr(event_addr); + if (!hfp_connection || hfp_connection->state != HFP_W4_RFCOMM_CONNECTED) return; + + if (status) { + hfp_emit_slc_connection_event(hfp_connection, status, rfcomm_event_channel_opened_get_con_handle(packet), event_addr); + remove_hfp_connection_context(hfp_connection); + } else { + hfp_connection->acl_handle = rfcomm_event_channel_opened_get_con_handle(packet); + hfp_connection->rfcomm_cid = rfcomm_event_channel_opened_get_rfcomm_cid(packet); + bd_addr_copy(hfp_connection->remote_addr, event_addr); + // uint16_t mtu = rfcomm_event_channel_opened_get_max_frame_size(packet); + // printf("RFCOMM channel open succeeded. hfp_connection %p, RFCOMM Channel ID 0x%02x, max frame size %u\n", hfp_connection, hfp_connection->rfcomm_cid, mtu); + + switch (hfp_connection->state){ + case HFP_W4_RFCOMM_CONNECTED: + hfp_connection->state = HFP_EXCHANGE_SUPPORTED_FEATURES; + break; + case HFP_W4_CONNECTION_ESTABLISHED_TO_SHUTDOWN: + hfp_connection->state = HFP_W2_DISCONNECT_RFCOMM; + // printf("Shutting down RFCOMM.\n"); + break; + default: + break; + } + rfcomm_request_can_send_now_event(hfp_connection->rfcomm_cid); + } + break; + + case RFCOMM_EVENT_CHANNEL_CLOSED: + rfcomm_cid = little_endian_read_16(packet,2); + hfp_connection = get_hfp_connection_context_for_rfcomm_cid(rfcomm_cid); + if (!hfp_connection) break; + if (hfp_connection->state == HFP_W4_RFCOMM_DISCONNECTED_AND_RESTART){ + hfp_connection->state = HFP_IDLE; + hfp_establish_service_level_connection(hfp_connection->remote_addr, hfp_connection->service_uuid, local_role); + break; + } + + hfp_emit_event(hfp_connection, HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_RELEASED, 0); + remove_hfp_connection_context(hfp_connection); + break; + + default: + break; + } +} // translates command string into hfp_command_t CMD static hfp_command_t parse_command(const char * line_buffer, int isHandsFree){ int offset = isHandsFree ? 0 : 2; @@ -1505,11 +1516,5 @@ void hfp_set_hf_run_for_context(void (*callback)(hfp_connection_t * hfp_connecti hfp_hf_run_for_context = callback; } -static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ - hfp_handle_hci_event(packet_type, channel, packet, size, HFP_ROLE_INVALID); -} - void hfp_init(void){ - hci_event_callback_registration.callback = &packet_handler; - hci_add_event_handler(&hci_event_callback_registration); } diff --git a/src/classic/hfp.h b/src/classic/hfp.h index 70946ca2a..4a59d2964 100644 --- a/src/classic/hfp.h +++ b/src/classic/hfp.h @@ -652,7 +652,8 @@ void hfp_set_hf_run_for_context(void (*callbcack)(hfp_connection_t * hfp_connect void hfp_init(void); void hfp_create_sdp_record(uint8_t * service, uint32_t service_record_handle, uint16_t service_uuid, int rfcomm_channel_nr, const char * name); -void hfp_handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size, hfp_role_t local_role); +void hfp_handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); +void hfp_handle_rfcomm_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size, hfp_role_t local_role); void hfp_emit_event(hfp_connection_t * hfp_connection, uint8_t event_subtype, uint8_t value); void hfp_emit_simple_event(hfp_connection_t * hfp_connection, uint8_t event_subtype); void hfp_emit_string_event(hfp_connection_t * hfp_connection, uint8_t event_subtype, const char * value); diff --git a/src/classic/hfp_ag.c b/src/classic/hfp_ag.c index 33e96e8ab..84f02847b 100644 --- a/src/classic/hfp_ag.c +++ b/src/classic/hfp_ag.c @@ -81,6 +81,8 @@ void set_hfp_ag_indicators(hfp_ag_indicator_t * indicators, int indicator_nr); int get_hfp_ag_indicators_nr(hfp_connection_t * context); hfp_ag_indicator_t * get_hfp_ag_indicators(hfp_connection_t * context); +static btstack_packet_callback_registration_t hci_event_callback_registration; + // gobals static const char default_hfp_ag_service_name[] = "Voice gateway"; @@ -2032,7 +2034,7 @@ static void rfcomm_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t hfp_run_for_context(get_hfp_connection_context_for_rfcomm_cid(rfcomm_cid)); return; } - hfp_handle_hci_event(packet_type, channel, packet, size, HFP_ROLE_AG); + hfp_handle_rfcomm_event(packet_type, channel, packet, size, HFP_ROLE_AG); break; default: break; @@ -2075,9 +2077,15 @@ void hfp_ag_init_call_hold_services(int call_hold_services_nr, const char * call void hfp_ag_init(uint16_t rfcomm_channel_nr){ + hfp_init(); + hci_event_callback_registration.callback = &hfp_handle_hci_event; + hci_add_event_handler(&hci_event_callback_registration); + rfcomm_register_service(&rfcomm_packet_handler, rfcomm_channel_nr, 0xffff); + + // used to set packet handler for outgoing rfcomm connections - could be handled by emitting an event to us hfp_set_ag_rfcomm_packet_handler(&rfcomm_packet_handler); hfp_ag_response_and_hold_active = 0; diff --git a/src/classic/hfp_hf.c b/src/classic/hfp_hf.c index e06d4cd6d..7f5ebcd26 100644 --- a/src/classic/hfp_hf.c +++ b/src/classic/hfp_hf.c @@ -66,6 +66,8 @@ #include "hci_dump.h" #include "l2cap.h" +static btstack_packet_callback_registration_t hci_event_callback_registration; + static const char default_hfp_hf_service_name[] = "Hands-Free unit"; static uint16_t hfp_supported_features = HFP_DEFAULT_HF_SUPPORTED_FEATURES; static uint8_t hfp_codecs_nr = 0; @@ -1099,7 +1101,7 @@ static void rfcomm_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t hfp_run_for_context(get_hfp_connection_context_for_rfcomm_cid(rfcomm_cid)); return; } - hfp_handle_hci_event(packet_type, channel, packet, size, HFP_ROLE_HF); + hfp_handle_rfcomm_event(packet_type, channel, packet, size, HFP_ROLE_HF); break; default: break; @@ -1110,8 +1112,14 @@ static void rfcomm_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t void hfp_hf_init(uint16_t rfcomm_channel_nr){ hfp_init(); + hci_event_callback_registration.callback = &hfp_handle_hci_event; + hci_add_event_handler(&hci_event_callback_registration); + rfcomm_register_service(rfcomm_packet_handler, rfcomm_channel_nr, 0xffff); + + // used to set packet handler for outgoing rfcomm connections - could be handled by emitting an event to us hfp_set_hf_rfcomm_packet_handler(&rfcomm_packet_handler); + hfp_set_hf_run_for_context(hfp_run_for_context); hfp_supported_features = HFP_DEFAULT_HF_SUPPORTED_FEATURES;