avrcp: use separate callback for avrcp open/close connection events

This commit is contained in:
Milanka Ringwald 2020-04-24 17:25:21 +02:00 committed by Matthias Ringwald
parent 9cf030dd9e
commit cee0e5b635
7 changed files with 131 additions and 147 deletions

View File

@ -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;

View File

@ -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':

View File

@ -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;
}

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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);