mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-03-26 11:37:10 +00:00
avrcp: use separate callback for avrcp open/close connection events
This commit is contained in:
parent
9cf030dd9e
commit
cee0e5b635
@ -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;
|
||||
|
@ -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':
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user