diff --git a/example/a2dp_sink_demo.c b/example/a2dp_sink_demo.c index dd9cd2563..69afa6ea6 100644 --- a/example/a2dp_sink_demo.c +++ b/example/a2dp_sink_demo.c @@ -225,6 +225,7 @@ static btstack_resample_t resample_instance; /* LISTING_START(MainConfiguration): Setup Audio Sink and AVRCP Controller services */ static void a2dp_sink_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * event, uint16_t event_size); +static void avrcp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); static void avrcp_controller_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); static void avrcp_target_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); static void hci_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); @@ -249,6 +250,7 @@ static int a2dp_and_avrcp_setup(void){ // Initialize AVRCP service. avrcp_init(); + avrcp_register_packet_handler(&avrcp_packet_handler); // Initialize AVRCP Controller avrcp_controller_init(); @@ -577,7 +579,7 @@ static void dump_sbc_configuration(avdtp_media_codec_configuration_sbc_t configu printf("\n"); } -static void avrcp_controller_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ +static void avrcp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ UNUSED(channel); UNUSED(size); uint16_t local_cid; @@ -590,13 +592,13 @@ static void avrcp_controller_packet_handler(uint8_t packet_type, uint16_t channe case AVRCP_SUBEVENT_CONNECTION_ESTABLISHED: { local_cid = avrcp_subevent_connection_established_get_avrcp_cid(packet); if (avrcp_cid != 0 && avrcp_cid != local_cid) { - printf("AVRCP Controller: Connection failed, expected 0x%02X cid, received 0x%02X\n", avrcp_cid, local_cid); + printf("AVRCP: Connection failed, expected 0x%02X cid, received 0x%02X\n", avrcp_cid, local_cid); return; } status = avrcp_subevent_connection_established_get_status(packet); if (status != ERROR_CODE_SUCCESS){ - printf("AVRCP Controller: Connection failed: status 0x%02x\n", status); + printf("AVRCP: Connection failed: status 0x%02x\n", status); avrcp_cid = 0; return; } @@ -604,7 +606,7 @@ static void avrcp_controller_packet_handler(uint8_t packet_type, uint16_t channe avrcp_cid = local_cid; avrcp_connected = 1; avrcp_subevent_connection_established_get_bd_addr(packet, adress); - printf("AVRCP Controller: Connected to %s, cid 0x%02x\n", bd_addr_to_str(adress), avrcp_cid); + printf("AVRCP: Connected to %s, cid 0x%02x\n", bd_addr_to_str(adress), avrcp_cid); // automatically enable notifications avrcp_controller_enable_notification(avrcp_cid, AVRCP_NOTIFICATION_EVENT_PLAYBACK_STATUS_CHANGED); @@ -612,15 +614,25 @@ static void avrcp_controller_packet_handler(uint8_t packet_type, uint16_t channe avrcp_controller_enable_notification(avrcp_cid, AVRCP_NOTIFICATION_EVENT_TRACK_CHANGED); return; } + case AVRCP_SUBEVENT_CONNECTION_RELEASED: - printf("AVRCP Controller: Channel released: cid 0x%02x\n", avrcp_subevent_connection_released_get_avrcp_cid(packet)); + printf("AVRCP: Channel released: cid 0x%02x\n", avrcp_subevent_connection_released_get_avrcp_cid(packet)); avrcp_cid = 0; avrcp_connected = 0; return; default: break; } +} +static void avrcp_controller_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ + UNUSED(channel); + UNUSED(size); + uint8_t status = 0xFF; + + if (packet_type != HCI_EVENT_PACKET) return; + if (hci_event_packet_get_type(packet) != HCI_EVENT_AVRCP_META) return; + status = packet[5]; if (!avrcp_cid) return; @@ -727,8 +739,6 @@ static void avrcp_controller_packet_handler(uint8_t packet_type, uint16_t channe static void avrcp_target_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ UNUSED(channel); UNUSED(size); - bd_addr_t address; - uint16_t local_cid; uint8_t status = ERROR_CODE_SUCCESS; if (packet_type != HCI_EVENT_PACKET) return; @@ -742,23 +752,7 @@ static void avrcp_target_packet_handler(uint8_t packet_type, uint16_t channel, u volume_percentage = volume * 100 / 127; printf("AVRCP Target : Volume set to %d%% (%d)\n", volume_percentage, volume); break; - case AVRCP_SUBEVENT_CONNECTION_ESTABLISHED: - local_cid = avrcp_subevent_connection_established_get_avrcp_cid(packet); - if (avrcp_cid != 0 && avrcp_cid != local_cid) { - printf("AVRCP Target : Connection failed, expected 0x%02X cid, received 0x%02X\n", avrcp_cid, local_cid); - return; - } - - status = avrcp_subevent_connection_established_get_status(packet); - if (status != ERROR_CODE_SUCCESS){ - printf("AVRCP Target : Connection failed: status 0x%02x\n", status); - avrcp_cid = 0; - return; - } - avrcp_cid = local_cid; - avrcp_subevent_connection_established_get_bd_addr(packet, address); - printf("AVRCP Target : Connected to %s, cid 0x%02x\n", bd_addr_to_str(address), avrcp_cid); - break; + case AVRCP_SUBEVENT_EVENT_IDS_QUERY: status = avrcp_target_supported_events(avrcp_cid, events_num, events, sizeof(events)); break; @@ -825,9 +819,6 @@ static void avrcp_target_packet_handler(uint8_t packet_type, uint16_t channel, u } break; } - case AVRCP_SUBEVENT_CONNECTION_RELEASED: - printf("AVRCP Target : Disconnected, cid 0x%02x\n", avrcp_subevent_connection_released_get_avrcp_cid(packet)); - return; default: printf("AVRCP Target : Event 0x%02x is not parsed\n", packet[2]); break; diff --git a/example/a2dp_source_demo.c b/example/a2dp_source_demo.c index 232645c35..f99fa27e2 100644 --- a/example/a2dp_source_demo.c +++ b/example/a2dp_source_demo.c @@ -194,8 +194,6 @@ static int hxcmod_initialized; static modcontext mod_context; static tracker_buffer_state trkbuf; -static uint16_t avrcp_controller_cid = 0; - /* AVRCP Target context START */ static const uint8_t subunit_info[] = { 0,0,0,0, @@ -258,6 +256,7 @@ avrcp_play_status_info_t play_info; /* LISTING_START(MainConfiguration): Setup Audio Source and AVRCP Target services */ static void a2dp_source_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * event, uint16_t event_size); +static void avrcp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); static void avrcp_target_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); static void avrcp_controller_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); #ifdef HAVE_BTSTACK_STDIN @@ -300,6 +299,7 @@ static int a2dp_source_and_avrcp_services_init(void){ avdtp_source_register_delay_reporting_category(media_tracker.local_seid); avrcp_init(); + avrcp_register_packet_handler(&avrcp_packet_handler); // Initialize AVRCP Target. avrcp_target_init(); avrcp_target_register_packet_handler(&avrcp_target_packet_handler); @@ -713,7 +713,7 @@ static void a2dp_source_packet_handler(uint8_t packet_type, uint16_t channel, ui } } -static void avrcp_target_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ +static void avrcp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ UNUSED(channel); UNUSED(size); bd_addr_t event_addr; @@ -724,28 +724,53 @@ static void avrcp_target_packet_handler(uint8_t packet_type, uint16_t channel, u if (hci_event_packet_get_type(packet) != HCI_EVENT_AVRCP_META) return; switch (packet[2]){ - case AVRCP_SUBEVENT_CONNECTION_ESTABLISHED: { + case AVRCP_SUBEVENT_CONNECTION_ESTABLISHED: local_cid = avrcp_subevent_connection_established_get_avrcp_cid(packet); - // if (avrcp_cid != 0 && avrcp_cid != local_cid) { - // printf("AVRCP Target: Connection failed, expected 0x%02X l2cap cid, received 0x%02X\n", avrcp_cid, local_cid); - // return; - // } - // if (avrcp_cid != local_cid) break; + if (media_tracker.avrcp_cid != 0 && media_tracker.avrcp_cid != local_cid) { + printf("AVRCP: Connection failed, expected 0x%02X l2cap cid, received 0x%02X\n", media_tracker.avrcp_cid, local_cid); + return; + } + if (media_tracker.avrcp_cid != local_cid) break; status = avrcp_subevent_connection_established_get_status(packet); if (status != ERROR_CODE_SUCCESS){ - printf("AVRCP Target: Connection failed, status 0x%02x\n", status); + printf("AVRCP: Connection failed, status 0x%02x\n", status); return; } media_tracker.avrcp_cid = local_cid; avrcp_subevent_connection_established_get_bd_addr(packet, event_addr); - printf("AVRCP Target: Connected to %s, avrcp_cid 0x%02x\n", bd_addr_to_str(event_addr), local_cid); avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, NULL, sizeof(tracks)/sizeof(avrcp_track_t)); avrcp_target_set_unit_info(media_tracker.avrcp_cid, AVRCP_SUBUNIT_TYPE_AUDIO, company_id); avrcp_target_set_subunit_info(media_tracker.avrcp_cid, AVRCP_SUBUNIT_TYPE_AUDIO, (uint8_t *)subunit_info, sizeof(subunit_info)); + + // automatically enable notifications + avrcp_controller_enable_notification(media_tracker.avrcp_cid, AVRCP_NOTIFICATION_EVENT_VOLUME_CHANGED); + printf("AVRCP: Channel successfully opened: media_tracker.avrcp_cid 0x%02x\n", media_tracker.avrcp_cid); return; - } + + case AVRCP_SUBEVENT_CONNECTION_RELEASED: + printf("AVRCP Target: Disconnected, avrcp_cid 0x%02x\n", avrcp_subevent_connection_released_get_avrcp_cid(packet)); + media_tracker.avrcp_cid = 0; + return; + default: + break; + } + + if (status != ERROR_CODE_SUCCESS){ + printf("Responding to event 0x%02x failed with status 0x%02x\n", packet[2], status); + } +} + +static void avrcp_target_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ + UNUSED(channel); + UNUSED(size); + uint8_t status = ERROR_CODE_SUCCESS; + + if (packet_type != HCI_EVENT_PACKET) return; + if (hci_event_packet_get_type(packet) != HCI_EVENT_AVRCP_META) return; + + switch (packet[2]){ case AVRCP_SUBEVENT_NOTIFICATION_VOLUME_CHANGED: printf("AVRCP Target: new volume %d\n", avrcp_subevent_notification_volume_changed_get_absolute_volume(packet)); break; @@ -782,10 +807,7 @@ static void avrcp_target_packet_handler(uint8_t packet_type, uint16_t channel, u } break; } - case AVRCP_SUBEVENT_CONNECTION_RELEASED: - printf("AVRCP Target: Disconnected, avrcp_cid 0x%02x\n", avrcp_subevent_connection_released_get_avrcp_cid(packet)); - media_tracker.avrcp_cid = 0; - return; + default: break; } @@ -798,45 +820,13 @@ static void avrcp_target_packet_handler(uint8_t packet_type, uint16_t channel, u static void avrcp_controller_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ UNUSED(channel); UNUSED(size); - uint16_t local_cid; uint8_t status = 0xFF; - bd_addr_t adress; if (packet_type != HCI_EVENT_PACKET) return; if (hci_event_packet_get_type(packet) != HCI_EVENT_AVRCP_META) return; - switch (packet[2]){ - case AVRCP_SUBEVENT_CONNECTION_ESTABLISHED: { - local_cid = avrcp_subevent_connection_established_get_avrcp_cid(packet); - if (avrcp_controller_cid != 0 && avrcp_controller_cid != local_cid) { - printf("AVRCP Controller: Connection failed, expected 0x%02X l2cap cid, received 0x%02X\n", avrcp_controller_cid, local_cid); - return; - } - - status = avrcp_subevent_connection_established_get_status(packet); - if (status != ERROR_CODE_SUCCESS){ - printf("AVRCP Controller: Connection failed: status 0x%02x\n", status); - avrcp_controller_cid = 0; - return; - } - - avrcp_controller_cid = local_cid; - avrcp_subevent_connection_established_get_bd_addr(packet, adress); - printf("AVRCP Controller: Channel successfully opened: %s, avrcp_controller_cid 0x%02x\n", bd_addr_to_str(adress), avrcp_controller_cid); - - // automatically enable notifications - avrcp_controller_enable_notification(avrcp_controller_cid, AVRCP_NOTIFICATION_EVENT_VOLUME_CHANGED); - return; - } - case AVRCP_SUBEVENT_CONNECTION_RELEASED: - printf("AVRCP Controller: Channel released: avrcp_controller_cid 0x%02x\n", avrcp_subevent_connection_released_get_avrcp_cid(packet)); - avrcp_controller_cid = 0; - return; - default: - break; - } status = packet[5]; - if (!avrcp_controller_cid) return; + if (!media_tracker.avrcp_cid) return; // ignore INTERIM status if (status == AVRCP_CTYPE_RESPONSE_INTERIM) return; @@ -902,15 +892,15 @@ static void stdin_process(char cmd){ case 't': printf(" - volume up\n"); - status = avrcp_controller_volume_up(avrcp_controller_cid); + status = avrcp_controller_volume_up(media_tracker.avrcp_cid); break; case 'T': printf(" - volume down\n"); - status = avrcp_controller_volume_down(avrcp_controller_cid); + status = avrcp_controller_volume_down(media_tracker.avrcp_cid); break; case 'v': printf(" - absolute volume of 50%% (64)\n"); - status = avrcp_controller_set_absolute_volume(avrcp_controller_cid, 64); + status = avrcp_controller_set_absolute_volume(media_tracker.avrcp_cid, 64); break; case 'x': diff --git a/src/classic/avrcp.c b/src/classic/avrcp.c index ecc4bf3d2..b0f88aec6 100644 --- a/src/classic/avrcp.c +++ b/src/classic/avrcp.c @@ -64,6 +64,8 @@ static avrcp_context_t * sdp_query_context; avrcp_context_t avrcp_controller_context; avrcp_context_t avrcp_target_context; +static btstack_packet_handler_t avrcp_callback; + static uint8_t attribute_value[45]; static const unsigned int attribute_value_buffer_size = sizeof(attribute_value); @@ -421,8 +423,9 @@ static void avrcp_finalize_connection(avrcp_connection_t * connection){ btstack_memory_avrcp_connection_free(connection); } -void avrcp_emit_connection_established(btstack_packet_handler_t callback, uint16_t avrcp_cid, bd_addr_t addr, uint8_t status){ - if (!callback) return; +static void avrcp_emit_connection_established(uint16_t avrcp_cid, bd_addr_t addr, uint8_t status){ + btstack_assert(avrcp_callback != NULL); + uint8_t event[12]; int pos = 0; event[pos++] = HCI_EVENT_AVRCP_META; @@ -433,11 +436,12 @@ void avrcp_emit_connection_established(btstack_packet_handler_t callback, uint16 pos += 6; little_endian_store_16(event, pos, avrcp_cid); pos += 2; - (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); + (*avrcp_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); } -void avrcp_emit_connection_closed(btstack_packet_handler_t callback, uint16_t avrcp_cid){ - if (!callback) return; +static void avrcp_emit_connection_closed(uint16_t avrcp_cid){ + btstack_assert(avrcp_callback != NULL); + uint8_t event[5]; int pos = 0; event[pos++] = HCI_EVENT_AVRCP_META; @@ -445,7 +449,7 @@ void avrcp_emit_connection_closed(btstack_packet_handler_t callback, uint16_t av event[pos++] = AVRCP_SUBEVENT_CONNECTION_RELEASED; little_endian_store_16(event, pos, avrcp_cid); pos += 2; - (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); + (*avrcp_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); } static void avrcp_handle_sdp_client_query_attribute_value(uint8_t *packet){ @@ -576,7 +580,7 @@ static void avrcp_handle_sdp_client_query_attribute_value(uint8_t *packet){ static void avrcp_handle_sdp_query_failed(avrcp_connection_t * connection, uint8_t status){ if (connection == NULL) return; log_info("AVRCP: SDP query failed with status 0x%02x.", status); - avrcp_emit_connection_established(avrcp_packet_handler_for_role(connection->role), connection->avrcp_cid, connection->remote_addr, status); + avrcp_emit_connection_established(connection->avrcp_cid, connection->remote_addr, status); avrcp_finalize_connection(connection); } @@ -650,54 +654,16 @@ static int avrcp_handle_incoming_connection_for_role(avrcp_role_t role, bd_addr_ return 1; } -static void avrcp_handle_open_connection_for_role(avrcp_role_t role, bd_addr_t event_addr, uint16_t local_cid, uint16_t l2cap_mtu, uint8_t status){ - // printf("AVRCP: avrcp_handle_open_connection_for_role %d\n", role); - - btstack_packet_handler_t packet_handler = avrcp_packet_handler_for_role(role); - if (!packet_handler) { - // printf("AVRCP: avrcp_handle_open_connection_for_role %d, PH not defined\n", role); - return; - } - avrcp_connection_t * connection = get_avrcp_connection_for_bd_addr_for_role(role, event_addr); - if (!connection) { - // printf("AVRCP: avrcp_handle_open_connection_for_role %d, no connection found\n", role); - return; - } - - if (connection->state == AVCTP_CONNECTION_OPENED) return; - - if (status != ERROR_CODE_SUCCESS){ - log_info("L2CAP connection to connection %s failed. status code 0x%02x", bd_addr_to_str(event_addr), status); - avrcp_emit_connection_established(packet_handler, connection->avrcp_cid, event_addr, status); - avrcp_finalize_connection(connection); - return; - } - +static void avrcp_handle_open_connection_for_role( avrcp_connection_t * connection, uint16_t local_cid, uint16_t l2cap_mtu){ connection->l2cap_signaling_cid = local_cid; connection->l2cap_mtu = l2cap_mtu; connection->incoming_declined = false; connection->song_length_ms = 0xFFFFFFFF; connection->song_position_ms = 0xFFFFFFFF; connection->playback_status = AVRCP_PLAYBACK_STATUS_ERROR; + connection->state = AVCTP_CONNECTION_OPENED; log_info("L2CAP_EVENT_CHANNEL_OPENED avrcp_cid 0x%02x, l2cap_signaling_cid 0x%02x, role %d", connection->avrcp_cid, connection->l2cap_signaling_cid, connection->role); - connection->state = AVCTP_CONNECTION_OPENED; - // emit twice for each role - avrcp_emit_connection_established(packet_handler, connection->avrcp_cid, event_addr, ERROR_CODE_SUCCESS); -} - -static void avrcp_handle_close_connection_for_role(avrcp_role_t role,uint16_t local_cid){ - // printf("AVRCP: avrcp_handle_close_connection_for_role %d\n", role); - btstack_packet_handler_t packet_handler = avrcp_packet_handler_for_role(role); - if (!packet_handler) return; - - avrcp_connection_t * connection = get_avrcp_connection_for_l2cap_signaling_cid_for_role(role, local_cid); - if (!connection) return; - - // printf("avrcp_handle_close_connection_for_role avrcp_cid 0x%02x, l2cap_signaling_cid 0x%02x, role %d\n", connection->avrcp_cid, connection->l2cap_signaling_cid, role); - - avrcp_emit_connection_closed(packet_handler, connection->avrcp_cid); - avrcp_finalize_connection(connection); } static avrcp_role_t avrcp_role_from_transport_header(uint8_t transport_header){ @@ -717,7 +683,6 @@ static void avrcp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t uint16_t local_cid; uint16_t l2cap_mtu; uint8_t status; - avrcp_connection_t * connection = NULL; avrcp_role_t role; btstack_packet_handler_t packet_handler; uint8_t status_target; @@ -725,6 +690,9 @@ static void avrcp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t bool decline_connection; bool outoing_active; + avrcp_connection_t * connection_controller; + avrcp_connection_t * connection_target; + switch (packet_type) { case L2CAP_DATA_PACKET: role = avrcp_role_from_transport_header(packet[0]); @@ -741,16 +709,17 @@ static void avrcp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t l2cap_event_incoming_connection_get_address(packet, event_addr); local_cid = l2cap_event_incoming_connection_get_local_cid(packet); outoing_active = false; - connection = get_avrcp_connection_for_bd_addr_for_role(AVRCP_TARGET, event_addr); - if (connection != NULL){ + + connection_target = get_avrcp_connection_for_bd_addr_for_role(AVRCP_TARGET, event_addr); + if (connection_target != NULL){ outoing_active = true; - connection->incoming_declined = true; + connection_target->incoming_declined = true; } - connection = get_avrcp_connection_for_bd_addr_for_role(AVRCP_CONTROLLER, event_addr); - if (connection != NULL){ + connection_controller = get_avrcp_connection_for_bd_addr_for_role(AVRCP_CONTROLLER, event_addr); + if (connection_controller != NULL){ outoing_active = true; - connection->incoming_declined = true; + connection_controller->incoming_declined = true; } decline_connection = outoing_active; @@ -778,32 +747,56 @@ static void avrcp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t status = l2cap_event_channel_opened_get_status(packet); local_cid = l2cap_event_channel_opened_get_local_cid(packet); l2cap_mtu = l2cap_event_channel_opened_get_remote_mtu(packet); + + connection_controller = get_avrcp_connection_for_bd_addr_for_role(AVRCP_CONTROLLER, event_addr); + connection_target = get_avrcp_connection_for_bd_addr_for_role(AVRCP_TARGET, event_addr); + if ((connection_controller == NULL) || (connection_target == NULL)) { + break; + } + + if (status != ERROR_CODE_SUCCESS){ + log_info("L2CAP connection to connection %s failed. status code 0x%02x", bd_addr_to_str(event_addr), status); + avrcp_emit_connection_established(connection_controller->avrcp_cid, event_addr, status); + avrcp_finalize_connection(connection_controller); + avrcp_finalize_connection(connection_target); + return; + } + + avrcp_handle_open_connection_for_role(connection_target, local_cid, l2cap_mtu); + avrcp_handle_open_connection_for_role(connection_controller, local_cid, l2cap_mtu); - avrcp_handle_open_connection_for_role(AVRCP_TARGET, event_addr, local_cid, l2cap_mtu, status); - avrcp_handle_open_connection_for_role(AVRCP_CONTROLLER, event_addr, local_cid, l2cap_mtu, status); + avrcp_emit_connection_established(connection_controller->avrcp_cid, event_addr, status); break; case L2CAP_EVENT_CHANNEL_CLOSED: - // data: event (8), len(8), channel (16) local_cid = l2cap_event_channel_closed_get_local_cid(packet); - avrcp_handle_close_connection_for_role(AVRCP_TARGET, local_cid); - avrcp_handle_close_connection_for_role(AVRCP_CONTROLLER, local_cid); + + connection_controller = get_avrcp_connection_for_l2cap_signaling_cid_for_role(AVRCP_CONTROLLER, local_cid); + connection_target = get_avrcp_connection_for_l2cap_signaling_cid_for_role(AVRCP_TARGET, local_cid); + if ((connection_controller == NULL) || (connection_target == NULL)) { + break; + } + avrcp_emit_connection_closed(connection_controller->avrcp_cid); + avrcp_finalize_connection(connection_controller); + + avrcp_emit_connection_closed(connection_target->avrcp_cid); + avrcp_finalize_connection(connection_target); break; case L2CAP_EVENT_CAN_SEND_NOW: local_cid = l2cap_event_can_send_now_get_local_cid(packet); - connection = get_avrcp_connection_for_l2cap_signaling_cid_for_role(AVRCP_TARGET, local_cid); - if (connection && connection->wait_to_send){ + connection_target = get_avrcp_connection_for_l2cap_signaling_cid_for_role(AVRCP_TARGET, local_cid); + if (connection_target && connection_target->wait_to_send){ // printf("AVRCP: L2CAP_EVENT_CAN_SEND_NOW target\n"); - connection->wait_to_send = 0; + connection_target->wait_to_send = 0; (*avrcp_target_packet_handler)(HCI_EVENT_PACKET, channel, packet, size); break; } - connection = get_avrcp_connection_for_l2cap_signaling_cid_for_role(AVRCP_CONTROLLER, local_cid); - if (connection && connection->wait_to_send){ + connection_controller = get_avrcp_connection_for_l2cap_signaling_cid_for_role(AVRCP_CONTROLLER, local_cid); + if (connection_controller && connection_controller->wait_to_send){ // printf("AVRCP: L2CAP_EVENT_CAN_SEND_NOW controller\n"); - connection->wait_to_send = 0; + connection_controller->wait_to_send = 0; (*avrcp_controller_packet_handler)(HCI_EVENT_PACKET, channel, packet, size); break; } @@ -901,3 +894,7 @@ void avrcp_register_target_packet_handler(btstack_packet_handler_t callback){ avrcp_target_packet_handler = callback; } +void avrcp_register_packet_handler(btstack_packet_handler_t callback){ + btstack_assert(callback != NULL); + avrcp_callback = callback; +} diff --git a/src/classic/avrcp.h b/src/classic/avrcp.h index 3bdf86bc8..024cda4c5 100644 --- a/src/classic/avrcp.h +++ b/src/classic/avrcp.h @@ -549,9 +549,6 @@ const char * avrcp_shuffle2str(uint8_t index); void avrcp_register_controller_packet_handler(btstack_packet_handler_t avrcp_controller_packet_handler); void avrcp_register_target_packet_handler(btstack_packet_handler_t avrcp_target_packet_handler); -void avrcp_emit_connection_established(btstack_packet_handler_t callback, uint16_t avrcp_cid, bd_addr_t addr, uint8_t status); -void avrcp_emit_connection_closed(btstack_packet_handler_t callback, uint16_t avrcp_cid); - uint8_t avrcp_cmd_opcode(uint8_t *packet, uint16_t size); avrcp_connection_t * get_avrcp_connection_for_l2cap_signaling_cid_for_role(avrcp_role_t role, uint16_t l2cap_cid); @@ -578,6 +575,12 @@ void avrcp_create_sdp_record(uint8_t controller, uint8_t * service, uint32_t */ void avrcp_init(void); +/** + * @brief Register callback for the AVRCP Controller client. + * @param callback + */ +void avrcp_register_packet_handler(btstack_packet_handler_t callback); + /** * @brief Connect to AVRCP service on a remote device, emits AVRCP_SUBEVENT_CONNECTION_ESTABLISHED with status * @param remote_addr diff --git a/test/avrcp/avrcp_controller_test.c b/test/avrcp/avrcp_controller_test.c index a787a31cf..1b2603fb0 100644 --- a/test/avrcp/avrcp_controller_test.c +++ b/test/avrcp/avrcp_controller_test.c @@ -348,6 +348,7 @@ int btstack_main(int argc, const char * argv[]){ // Initialize AVRCP service. avrcp_init(); + avrcp_register_packet_handler(&packet_handler); // Initialize AVRCP COntroller avrcp_controller_init(); avrcp_controller_register_packet_handler(&packet_handler); diff --git a/test/pts/avrcp_controller_test.c b/test/pts/avrcp_controller_test.c index 638684626..fb5095d8b 100644 --- a/test/pts/avrcp_controller_test.c +++ b/test/pts/avrcp_controller_test.c @@ -1136,6 +1136,7 @@ int btstack_main(int argc, const char * argv[]){ // Initialize AVRCP service. avrcp_init(); + avrcp_register_packet_handler(&packet_handler); // Initialize AVRCP Controller avrcp_controller_init(); avrcp_controller_register_packet_handler(&packet_handler); diff --git a/test/pts/avrcp_target_test.c b/test/pts/avrcp_target_test.c index e5a94bf8b..dc79ef65a 100644 --- a/test/pts/avrcp_target_test.c +++ b/test/pts/avrcp_target_test.c @@ -845,6 +845,7 @@ int btstack_main(int argc, const char * argv[]){ // Initialize AVRCP service avrcp_init(); + avrcp_register_packet_handler(&avrcp_target_packet_handler); // Initialize AVRCP Target. avrcp_target_init(); avrcp_target_register_packet_handler(&avrcp_target_packet_handler);