avrcp_controller: automatically query supported events when registering for notifications

This commit is contained in:
Milanka Ringwald 2021-10-26 09:25:26 +02:00
parent 1f94eaa583
commit 2ac1dc76c9
4 changed files with 52 additions and 36 deletions

View File

@ -29,13 +29,14 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
### Fixed
- A2DP Source: fix reconfigure
- AVRCP Controller: prevent registering notifications for unsupported events
- RFCOMM: fixed handling of remote port configuration command
- HFP AG: fix accept incoming connection while audio connection is established
- PBAP Client: handle chunked vCard Listing
- SM: Work around for unexpected Windows 10 disconnect for BR Secure Connections (SMP over BR timeout)
- SM: support storing bonding information for devices with identical IRK but different public addresses
- GAP: restart advertising when private address changes
### Changed
- Drop iOS support
- HCI: provide status instead of undocumented int error code and bool for API functions
@ -51,6 +52,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- HFP: enhanced VRA: HFP_SUBEVENT_VOICE_RECOGNITION_ACTIVATED is emitted after VRA is ready and the the audio connection is established. This simplifies HFP HF client logic, i.e. client can call `hfp_hf_enhanced_voice_recognition_report_ready_for_audio directly` upon reception of HFP_SUBEVENT_VOICE_RECOGNITION_ACTIVATED event.
- AVDTP: media config validator is called with preview of media codec configuration event and configured separately for sink/source
- AVRCP: use PANEL as default unit + subunit info
- AVRCP Controller: automatically query supported events when registering for notifications
- Run Loop: new functionality for HCI transport drivers and inter-process communication
- *btstack_run_loop_poll_data_sources_from_irq*: used to transfer control from IRQ handler to main thread/run loop
- *btstack_run_loop_execute_on_main_thread*: schedule code execution on main thread from other thread

View File

@ -752,11 +752,14 @@ static void avrcp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t
media_tracker.avrcp_cid = local_cid;
avrcp_subevent_connection_established_get_bd_addr(packet, event_addr);
printf("AVRCP: Channel to %s successfully opened, avrcp_cid 0x%02x\n", bd_addr_to_str(event_addr), media_tracker.avrcp_cid);
avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, NULL, sizeof(tracks)/sizeof(avrcp_track_t));
avrcp_controller_get_supported_events(media_tracker.avrcp_cid);
printf("AVRCP: Channel successfully opened: media_tracker.avrcp_cid 0x%02x\n", media_tracker.avrcp_cid);
printf("Enable Volume Change notification\n");
avrcp_controller_enable_notification(media_tracker.avrcp_cid, AVRCP_NOTIFICATION_EVENT_VOLUME_CHANGED);
printf("Enable Battery Status Change notification\n");
avrcp_controller_enable_notification(media_tracker.avrcp_cid, AVRCP_NOTIFICATION_EVENT_BATT_STATUS_CHANGED);
return;
case AVRCP_SUBEVENT_CONNECTION_RELEASED:
@ -846,14 +849,6 @@ static void avrcp_controller_packet_handler(uint8_t packet_type, uint16_t channe
// see avrcp_battery_status_t
printf("AVRCP Controller: battery status changed %d\n", avrcp_subevent_notification_event_batt_status_changed_get_battery_status(packet));
break;
case AVRCP_SUBEVENT_GET_CAPABILITY_EVENT_ID:
printf("Remote supports EVENT_ID 0x%02x\n", avrcp_subevent_get_capability_event_id_get_event_id(packet));
break;
case AVRCP_SUBEVENT_GET_CAPABILITY_EVENT_ID_DONE:
printf("automatically enable notifications\n");
avrcp_controller_enable_notification(media_tracker.avrcp_cid, AVRCP_NOTIFICATION_EVENT_VOLUME_CHANGED);
avrcp_controller_enable_notification(media_tracker.avrcp_cid, AVRCP_NOTIFICATION_EVENT_BATT_STATUS_CHANGED);
break;
default:
break;
}

View File

@ -557,7 +557,8 @@ typedef struct {
uint16_t remote_supported_notifications;
bool remote_supported_notifications_queried;
bool remote_supported_notifications_suppress_emit_result;
uint16_t notifications_to_register;
uint16_t notifications_to_deregister;
uint8_t notifications_transaction_label[AVRCP_NOTIFICATION_EVENT_MAX_VALUE+1];

View File

@ -93,35 +93,37 @@ static int avrcp_controller_supports_browsing(uint16_t controller_supported_feat
}
static void avrcp_controller_emit_supported_events(avrcp_connection_t * connection){
uint8_t event_id;
uint8_t offset;
uint8_t event[9];
uint8_t ctype = (uint8_t) AVRCP_CTYPE_RESPONSE_CHANGED_STABLE;
uint8_t event_id;
for (event_id = (uint8_t) AVRCP_NOTIFICATION_EVENT_PLAYBACK_STATUS_CHANGED; event_id < (uint8_t) AVRCP_NOTIFICATION_EVENT_MAX_VALUE; event_id++){
if ( (connection->remote_supported_notifications & (1<<event_id)) == 0){
continue;
}
offset = 0;
event[offset++] = HCI_EVENT_AVRCP_META;
event[offset++] = sizeof(event) - 2;
event[offset++] = AVRCP_SUBEVENT_GET_CAPABILITY_EVENT_ID;
little_endian_store_16(event, offset, connection->avrcp_cid);
offset += 2;
event[offset++] = ctype;
event[offset++] = 0;
event[offset++] = event_id;
(*avrcp_controller_context.avrcp_callback)(HCI_EVENT_PACKET, 0, event, offset);
uint8_t event[8];
uint8_t pos = 0;
event[pos++] = HCI_EVENT_AVRCP_META;
event[pos++] = sizeof(event) - 2;
event[pos++] = AVRCP_SUBEVENT_GET_CAPABILITY_EVENT_ID;
little_endian_store_16(event, pos, connection->avrcp_cid);
pos += 2;
event[pos++] = ctype;
event[pos++] = 0;
event[pos++] = event_id;
UNUSED(pos);
(*avrcp_controller_context.avrcp_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
}
offset = 0;
event[offset++] = HCI_EVENT_AVRCP_META;
event[offset++] = sizeof(event) - 2;
event[offset++] = AVRCP_SUBEVENT_GET_CAPABILITY_EVENT_ID_DONE;
little_endian_store_16(event, offset, connection->avrcp_cid);
offset += 2;
event[offset++] = ctype;
event[offset++] = 0;
uint8_t event[7];
uint8_t pos = 0;
event[pos++] = HCI_EVENT_AVRCP_META;
event[pos++] = sizeof(event) - 2;
event[pos++] = AVRCP_SUBEVENT_GET_CAPABILITY_EVENT_ID_DONE;
little_endian_store_16(event, pos, connection->avrcp_cid);
pos += 2;
event[pos++] = ctype;
event[pos++] = 0;
UNUSED(pos);
(*avrcp_controller_context.avrcp_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
}
@ -655,7 +657,7 @@ static void avrcp_controller_get_capabilities_for_connection(avrcp_connection_t
}
static uint8_t avrcp_controller_register_notification(avrcp_connection_t * connection, avrcp_notification_event_id_t event_id){
if ( (connection->remote_supported_notifications & (1 << event_id)) == 0){
if (connection->remote_supported_notifications_queried && (connection->remote_supported_notifications & (1 << event_id)) == 0){
return ERROR_CODE_UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE;
}
if ( (connection->notifications_to_deregister & (1 << event_id)) != 0){
@ -669,6 +671,12 @@ static uint8_t avrcp_controller_register_notification(avrcp_connection_t * conne
}
connection->notifications_to_register |= (1 << event_id);
if (!connection->remote_supported_notifications_queried){
connection->remote_supported_notifications_suppress_emit_result = true;
avrcp_controller_get_capabilities_for_connection(connection, AVRCP_CAPABILITY_ID_EVENT);
return ERROR_CODE_SUCCESS;
}
avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
return ERROR_CODE_SUCCESS;
}
@ -1000,6 +1008,10 @@ static void avrcp_handle_l2cap_data_packet_for_signaling_connection(avrcp_connec
uint8_t event_id = packet[pos++];
connection->remote_supported_notifications |= (1 << event_id);
}
if (connection->remote_supported_notifications_suppress_emit_result){
connection->remote_supported_notifications_suppress_emit_result = false;
break;
}
avrcp_controller_emit_supported_events(connection);
break;
@ -1400,7 +1412,13 @@ uint8_t avrcp_controller_get_supported_events(uint16_t avrcp_cid){
return ERROR_CODE_COMMAND_DISALLOWED;
}
avrcp_controller_get_capabilities_for_connection(connection, AVRCP_CAPABILITY_ID_EVENT);
if (!connection->remote_supported_notifications_queried){
connection->remote_supported_notifications_queried = true;
avrcp_controller_get_capabilities_for_connection(connection, AVRCP_CAPABILITY_ID_EVENT);
return ERROR_CODE_SUCCESS;
}
avrcp_controller_emit_supported_events(connection);
return ERROR_CODE_SUCCESS;
}