diff --git a/src/btstack_defines.h b/src/btstack_defines.h index 27d82699d..63d31ed55 100644 --- a/src/btstack_defines.h +++ b/src/btstack_defines.h @@ -915,10 +915,12 @@ typedef uint8_t sm_key_t[16]; /** HFP Subevent */ /** - * @format 11H + * @format 11HB1 * @param subevent_code * @param status 0 == OK * @param con_handle + * @param bd_addr + * @param negotiated_codec */ #define HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_ESTABLISHED 0x01 @@ -929,10 +931,12 @@ typedef uint8_t sm_key_t[16]; #define HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_RELEASED 0x02 /** - * @format 11H + * @format 11HB1 * @param subevent_code * @param status 0 == OK * @param handle + * @param bd_addr + * @param negotiated_codec */ #define HFP_SUBEVENT_AUDIO_CONNECTION_ESTABLISHED 0x03 @@ -975,9 +979,10 @@ typedef uint8_t sm_key_t[16]; #define HFP_SUBEVENT_EXTENDED_AUDIO_GATEWAY_ERROR 0x08 /** - * @format 11 + * @format 111 * @param subevent_code * @param status + * @param negotiated_codec */ #define HFP_SUBEVENT_CODECS_CONNECTION_COMPLETE 0x09 diff --git a/src/btstack_event.h b/src/btstack_event.h index 4c04eae3c..9c55f88fe 100644 --- a/src/btstack_event.h +++ b/src/btstack_event.h @@ -2739,6 +2739,24 @@ static inline uint8_t hfp_subevent_service_level_connection_established_get_stat static inline hci_con_handle_t hfp_subevent_service_level_connection_established_get_con_handle(const uint8_t * event){ return little_endian_read_16(event, 4); } +/** + * @brief Get field bd_addr from event HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_ESTABLISHED + * @param event packet + * @param Pointer to storage for bd_addr + * @note: btstack_type B + */ +static inline void hfp_subevent_service_level_connection_established_get_bd_addr(const uint8_t * event, bd_addr_t bd_addr){ + reverse_bd_addr(&event[6], bd_addr); +} +/** + * @brief Get field negotiated_codec from event HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_ESTABLISHED + * @param event packet + * @return negotiated_codec + * @note: btstack_type 1 + */ +static inline uint8_t hfp_subevent_service_level_connection_established_get_negotiated_codec(const uint8_t * event){ + return event[12]; +} /** @@ -2759,6 +2777,24 @@ static inline uint8_t hfp_subevent_audio_connection_established_get_status(const static inline hci_con_handle_t hfp_subevent_audio_connection_established_get_handle(const uint8_t * event){ return little_endian_read_16(event, 4); } +/** + * @brief Get field bd_addr from event HFP_SUBEVENT_AUDIO_CONNECTION_ESTABLISHED + * @param event packet + * @param Pointer to storage for bd_addr + * @note: btstack_type B + */ +static inline void hfp_subevent_audio_connection_established_get_bd_addr(const uint8_t * event, bd_addr_t bd_addr){ + reverse_bd_addr(&event[6], bd_addr); +} +/** + * @brief Get field negotiated_codec from event HFP_SUBEVENT_AUDIO_CONNECTION_ESTABLISHED + * @param event packet + * @return negotiated_codec + * @note: btstack_type 1 + */ +static inline uint8_t hfp_subevent_audio_connection_established_get_negotiated_codec(const uint8_t * event){ + return event[12]; +} /** @@ -2846,6 +2882,15 @@ static inline uint8_t hfp_subevent_extended_audio_gateway_error_get_error(const static inline uint8_t hfp_subevent_codecs_connection_complete_get_status(const uint8_t * event){ return event[3]; } +/** + * @brief Get field negotiated_codec from event HFP_SUBEVENT_CODECS_CONNECTION_COMPLETE + * @param event packet + * @return negotiated_codec + * @note: btstack_type 1 + */ +static inline uint8_t hfp_subevent_codecs_connection_complete_get_negotiated_codec(const uint8_t * event){ + return event[4]; +} diff --git a/src/classic/hfp.c b/src/classic/hfp.c index 3ccedea7c..ca99f46b0 100644 --- a/src/classic/hfp.c +++ b/src/classic/hfp.c @@ -129,7 +129,7 @@ int send_str_over_rfcomm(uint16_t cid, char * command){ return 1; } -int hfp_supports_codec(uint8_t codec, int codecs_nr, uint16_t * codecs){ +int hfp_supports_codec(uint8_t codec, int codecs_nr, uint8_t * codecs){ int i; for (i = 0; i < codecs_nr; i++){ if (codecs[i] == codec) return 1; @@ -203,6 +203,17 @@ void hfp_emit_simple_event(btstack_packet_handler_t callback, uint8_t event_subt (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); } +void hfp_emit_codec_event(btstack_packet_handler_t callback, uint8_t status, uint8_t codec){ + if (!callback) return; + uint8_t event[5]; + event[0] = HCI_EVENT_HFP_META; + event[1] = sizeof(event) - 2; + event[2] = HFP_SUBEVENT_CODECS_CONNECTION_COMPLETE; + event[3] = status; // status 0 == OK + event[4] = codec; + (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); +} + void hfp_emit_event(btstack_packet_handler_t callback, uint8_t event_subtype, uint8_t value){ if (!callback) return; uint8_t event[4]; @@ -213,14 +224,19 @@ void hfp_emit_event(btstack_packet_handler_t callback, uint8_t event_subtype, ui (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); } -void hfp_emit_connection_event(btstack_packet_handler_t callback, uint8_t event_subtype, uint8_t status, hci_con_handle_t con_handle){ +void hfp_emit_connection_event(btstack_packet_handler_t callback, uint8_t event_subtype, uint8_t status, hci_con_handle_t con_handle, bd_addr_t addr, uint8_t codec){ if (!callback) return; - uint8_t event[6]; - event[0] = HCI_EVENT_HFP_META; - event[1] = sizeof(event) - 2; - event[2] = event_subtype; - event[3] = status; // status 0 == OK - little_endian_store_16(event, 4, con_handle); + uint8_t event[13]; + int pos = 0; + event[pos++] = HCI_EVENT_HFP_META; + event[pos++] = sizeof(event) - 2; + event[pos++] = event_subtype; + event[pos++] = status; // status 0 == OK + little_endian_store_16(event, pos, con_handle); + pos += 2; + reverse_bd_addr(addr,&event[pos]); + pos += 6; + event[pos] = codec; (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); } @@ -291,7 +307,7 @@ void hfp_reset_context_flags(hfp_connection_t * hfp_connection){ // establish codecs hfp_connection hfp_connection->suggested_codec = 0; - hfp_connection->negotiated_codec = 0; + hfp_connection->negotiated_codec = HFP_CODEC_CVSD; hfp_connection->codec_confirmed = 0; hfp_connection->establish_audio_connection = 0; @@ -327,7 +343,6 @@ static hfp_connection_t * provide_hfp_connection_context_for_bd_addr(bd_addr_t b hfp_connection_t * hfp_connection = get_hfp_connection_context_for_bd_addr(bd_addr); if (hfp_connection) return hfp_connection; hfp_connection = create_hfp_connection_context(); - printf("created hfp_connection for address %s\n", bd_addr_to_str(bd_addr)); memcpy(hfp_connection->remote_addr, bd_addr, 6); return hfp_connection; } @@ -510,17 +525,17 @@ void hfp_handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *packet rfcomm_event_channel_opened_get_bd_addr(packet, event_addr); status = rfcomm_event_channel_opened_get_status(packet); - // printf("RFCOMM_EVENT_CHANNEL_OPENED packet_handler adddr %s, status %u\n", bd_addr_to_str(event_addr), status); - + 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_connection_event(hfp_callback, HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_ESTABLISHED, status, rfcomm_event_channel_opened_get_con_handle(packet)); + hfp_emit_connection_event(hfp_callback, HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_ESTABLISHED, status, rfcomm_event_channel_opened_get_con_handle(packet), event_addr, hfp_connection->negotiated_codec); 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); @@ -608,7 +623,7 @@ void hfp_handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *packet hfp_connection->sco_handle = sco_handle; hfp_connection->establish_audio_connection = 0; hfp_connection->state = HFP_AUDIO_CONNECTION_ESTABLISHED; - hfp_emit_connection_event(hfp_callback, HFP_SUBEVENT_AUDIO_CONNECTION_ESTABLISHED, packet[2], sco_handle); + hfp_emit_connection_event(hfp_callback, HFP_SUBEVENT_AUDIO_CONNECTION_ESTABLISHED, packet[2], sco_handle, event_addr, hfp_connection->negotiated_codec); break; } diff --git a/src/classic/hfp.h b/src/classic/hfp.h index 0ed0a1bbb..51e760f7c 100644 --- a/src/classic/hfp.h +++ b/src/classic/hfp.h @@ -489,7 +489,7 @@ typedef struct hfp_connection { // TODO: rename into hf_codecs_nr int remote_codecs_nr; - uint16_t remote_codecs[HFP_MAX_INDICATOR_DESC_SIZE]; + uint8_t remote_codecs[HFP_MAX_INDICATOR_DESC_SIZE]; int ag_indicators_nr; hfp_ag_indicator_t ag_indicators[HFP_MAX_INDICATOR_DESC_SIZE]; @@ -628,7 +628,8 @@ void hfp_handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *packet void hfp_emit_event(btstack_packet_handler_t callback, uint8_t event_subtype, uint8_t value); void hfp_emit_simple_event(btstack_packet_handler_t callback, uint8_t event_subtype); void hfp_emit_string_event(btstack_packet_handler_t callback, uint8_t event_subtype, const char * value); -void hfp_emit_connection_event(btstack_packet_handler_t callback, uint8_t event_subtype, uint8_t status, hci_con_handle_t con_handle); +void hfp_emit_connection_event(btstack_packet_handler_t callback, uint8_t event_subtype, uint8_t status, hci_con_handle_t con_handle, bd_addr_t addr, uint8_t codec); +void hfp_emit_codec_event(btstack_packet_handler_t callback, uint8_t status, uint8_t codec); hfp_connection_t * get_hfp_connection_context_for_rfcomm_cid(uint16_t cid); hfp_connection_t * get_hfp_connection_context_for_bd_addr(bd_addr_t bd_addr); @@ -644,7 +645,7 @@ void hfp_reset_context_flags(hfp_connection_t * connection); void hfp_release_audio_connection(hfp_connection_t * connection); void hfp_setup_synchronous_connection(hfp_connection_t * connection); -int hfp_supports_codec(uint8_t codec, int codecs_nr, uint16_t * codecs); +int hfp_supports_codec(uint8_t codec, int codecs_nr, uint8_t * codecs); const char * hfp_hf_feature(int index); const char * hfp_ag_feature(int index); diff --git a/src/classic/hfp_ag.c b/src/classic/hfp_ag.c index 84f7bc9a6..03787d8b0 100644 --- a/src/classic/hfp_ag.c +++ b/src/classic/hfp_ag.c @@ -519,8 +519,8 @@ static int hfp_ag_set_response_and_hold(uint16_t cid, int state){ } static uint8_t hfp_ag_suggest_codec(hfp_connection_t *hfp_connection){ - if (hfp_supports_codec(HFP_CODEC_MSBC, hfp_codecs_nr, (uint16_t *)hfp_codecs)){ - if (hfp_supports_codec(HFP_CODEC_MSBC, hfp_connection->remote_codecs_nr, (uint16_t *)(hfp_connection->remote_codecs))){ + if (hfp_supports_codec(HFP_CODEC_MSBC, hfp_codecs_nr, hfp_codecs)){ + if (hfp_supports_codec(HFP_CODEC_MSBC, hfp_connection->remote_codecs_nr, hfp_connection->remote_codecs)){ return HFP_CODEC_MSBC; } } @@ -587,7 +587,7 @@ static int codecs_exchange_state_machine(hfp_connection_t * hfp_connection){ } hfp_connection->negotiated_codec = hfp_connection->codec_confirmed; hfp_connection->codecs_state = HFP_CODECS_EXCHANGED; - hfp_emit_event(hfp_callback, HFP_SUBEVENT_CODECS_CONNECTION_COMPLETE, 0); + hfp_emit_codec_event(hfp_callback, 0, hfp_connection->negotiated_codec); hfp_ag_ok(hfp_connection->rfcomm_cid); return 1; default: @@ -610,7 +610,7 @@ static void hfp_init_link_settings(hfp_connection_t * hfp_connection){ static void hfp_ag_slc_established(hfp_connection_t * hfp_connection){ hfp_connection->state = HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED; - hfp_emit_connection_event(hfp_callback, HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_ESTABLISHED, 0, hfp_connection->acl_handle); + hfp_emit_connection_event(hfp_callback, HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_ESTABLISHED, 0, hfp_connection->acl_handle, hfp_connection->remote_addr, hfp_connection->negotiated_codec); hfp_init_link_settings(hfp_connection); diff --git a/src/classic/hfp_hf.c b/src/classic/hfp_hf.c index c25045d98..7b72d7dd9 100644 --- a/src/classic/hfp_hf.c +++ b/src/classic/hfp_hf.c @@ -515,8 +515,8 @@ static int codecs_exchange_state_machine(hfp_connection_t * hfp_connection){ hfp_hf_cmd_trigger_codec_connection_setup(hfp_connection->rfcomm_cid); break; - case HFP_CMD_AG_SUGGESTED_CODEC: - if (hfp_supports_codec(hfp_connection->suggested_codec, hfp_codecs_nr, (uint16_t *)hfp_codecs)){ + case HFP_CMD_AG_SUGGESTED_CODEC:{ + if (hfp_supports_codec(hfp_connection->suggested_codec, hfp_codecs_nr, hfp_codecs)){ hfp_connection->codec_confirmed = hfp_connection->suggested_codec; hfp_connection->ok_pending = 1; hfp_connection->codecs_state = HFP_CODECS_HF_CONFIRMED_CODEC; @@ -531,7 +531,7 @@ static int codecs_exchange_state_machine(hfp_connection_t * hfp_connection){ } break; - + } default: break; } @@ -828,7 +828,8 @@ static void hfp_init_link_settings(hfp_connection_t * hfp_connection){ static void hfp_ag_slc_established(hfp_connection_t * hfp_connection){ hfp_connection->state = HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED; - hfp_emit_connection_event(hfp_callback, HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_ESTABLISHED, 0, hfp_connection->acl_handle); + + hfp_emit_connection_event(hfp_callback, HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_ESTABLISHED, 0, hfp_connection->acl_handle, hfp_connection->remote_addr, hfp_connection->negotiated_codec); hfp_init_link_settings(hfp_connection); // restore volume settings hfp_connection->speaker_gain = hfp_hf_speaker_gain; @@ -936,7 +937,8 @@ static void hfp_hf_switch_on_ok(hfp_connection_t *hfp_connection){ break; case HFP_CODECS_HF_CONFIRMED_CODEC: hfp_connection->codecs_state = HFP_CODECS_EXCHANGED; - hfp_emit_event(hfp_callback, HFP_SUBEVENT_CODECS_CONNECTION_COMPLETE, 0); + hfp_connection->negotiated_codec = hfp_connection->suggested_codec; + hfp_emit_codec_event(hfp_callback, 0, hfp_connection->negotiated_codec); break; default: break;