diff --git a/example/a2dp_sink_demo.c b/example/a2dp_sink_demo.c index 3a2008e6a..fd6e135bf 100644 --- a/example/a2dp_sink_demo.c +++ b/example/a2dp_sink_demo.c @@ -146,21 +146,6 @@ static media_codec_configuration_sbc_t sbc_configuration; static int volume_percentage = 0; static avrcp_battery_status_t battery_status = AVRCP_BATTERY_STATUS_WARNING; -#ifdef SUPPORT_VOLUME_CHANGE_NOTIFICATION - -static uint8_t events[] = { - AVRCP_NOTIFICATION_EVENT_PLAYBACK_STATUS_CHANGED, - AVRCP_NOTIFICATION_EVENT_TRACK_CHANGED, - AVRCP_NOTIFICATION_EVENT_VOLUME_CHANGED, - AVRCP_NOTIFICATION_EVENT_BATT_STATUS_CHANGED -}; -#endif - -static uint8_t companies_num = 1; -static uint8_t companies[] = { - 0x00, 0x19, 0x58 //BT SIG registered CompanyID -}; - #ifdef HAVE_BTSTACK_STDIN // pts: static const char * device_addr_string = "6C:72:E7:10:22:EE"; diff --git a/example/a2dp_source_demo.c b/example/a2dp_source_demo.c index c10fe11e8..ba8d35bec 100644 --- a/example/a2dp_source_demo.c +++ b/example/a2dp_source_demo.c @@ -200,20 +200,6 @@ static modcontext mod_context; static tracker_buffer_state trkbuf; /* AVRCP Target context START */ -static uint8_t companies_num = 1; -static uint8_t companies[] = { - 0x00, 0x19, 0x58 //BT SIG registered CompanyID -}; - -static uint8_t events_num = 6; -static uint8_t events[] = { - AVRCP_NOTIFICATION_EVENT_PLAYBACK_STATUS_CHANGED, - AVRCP_NOTIFICATION_EVENT_TRACK_CHANGED, - AVRCP_NOTIFICATION_EVENT_PLAYER_APPLICATION_SETTING_CHANGED, - AVRCP_NOTIFICATION_EVENT_NOW_PLAYING_CONTENT_CHANGED, - AVRCP_NOTIFICATION_EVENT_AVAILABLE_PLAYERS_CHANGED, - AVRCP_NOTIFICATION_EVENT_ADDRESSED_PLAYER_CHANGED -}; typedef struct { uint8_t track_id[8]; @@ -788,12 +774,6 @@ static void avrcp_target_packet_handler(uint8_t packet_type, uint16_t channel, u avrcp_operation_id_t operation_id; switch (packet[2]){ - case AVRCP_SUBEVENT_EVENT_IDS_QUERY: - status = avrcp_target_supported_events(media_tracker.avrcp_cid, events_num, events, sizeof(events)); - break; - case AVRCP_SUBEVENT_COMPANY_IDS_QUERY: - status = avrcp_target_supported_companies(media_tracker.avrcp_cid, companies_num, companies, sizeof(companies)); - break; case AVRCP_SUBEVENT_PLAY_STATUS_QUERY: status = avrcp_target_play_status(media_tracker.avrcp_cid, play_info.song_length_ms, play_info.song_position_ms, play_info.status); break; diff --git a/src/classic/avrcp.h b/src/classic/avrcp.h index 33d381afa..d976f9e4e 100644 --- a/src/classic/avrcp.h +++ b/src/classic/avrcp.h @@ -560,6 +560,8 @@ typedef struct { uint16_t target_supported_notifications; bool target_supported_notifications_queried; bool target_supported_notifications_suppress_emit_result; + const uint32_t *target_supported_companies; + uint8_t target_supported_companies_num; uint16_t notifications_to_register; uint16_t notifications_to_deregister; diff --git a/src/classic/avrcp_target.c b/src/classic/avrcp_target.c index db6116378..1152abbf9 100644 --- a/src/classic/avrcp_target.c +++ b/src/classic/avrcp_target.c @@ -572,28 +572,69 @@ static inline uint8_t avrcp_prepare_vendor_dependent_response(uint16_t avrcp_cid return avrcp_prepare_vendor_dependent_response_for_connection(*out_connection, pdu_id, param_length); } -static uint8_t avrcp_target_capability(uint16_t avrcp_cid, avrcp_capability_id_t capability_id, uint8_t num_capabilities, const uint8_t *capabilities, uint8_t capabilities_size){ - avrcp_connection_t * connection = NULL; - uint8_t status = avrcp_prepare_vendor_dependent_response(avrcp_cid, &connection, AVRCP_PDU_ID_GET_CAPABILITIES, 2 + capabilities_size); + +static uint8_t avrcp_target_supported_events(avrcp_connection_t * connection){ + uint8_t num_events = 0; + uint8_t event_id; + uint8_t events[(uint8_t) AVRCP_NOTIFICATION_EVENT_LAST_INDEX]; + + for (event_id = (uint8_t) AVRCP_NOTIFICATION_EVENT_FIRST_INDEX; event_id < (uint8_t) AVRCP_NOTIFICATION_EVENT_LAST_INDEX; event_id++){ + if ((connection->target_supported_notifications & (1<cmd_operands[connection->cmd_operands_length++] = capability_id; - connection->cmd_operands[connection->cmd_operands_length++] = num_capabilities; - (void)memcpy(connection->cmd_operands + connection->cmd_operands_length, - capabilities, capabilities_size); - connection->cmd_operands_length += capabilities_size; + connection->cmd_operands[connection->cmd_operands_length++] = AVRCP_CAPABILITY_ID_EVENT; + connection->cmd_operands[connection->cmd_operands_length++] = num_events; + + (void)memcpy(connection->cmd_operands + connection->cmd_operands_length, events, events_size); + connection->cmd_operands_length += events_size; + + connection->state = AVCTP_W2_SEND_RESPONSE; + avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid); + return ERROR_CODE_SUCCESS; +} + +static uint8_t avrcp_target_supported_companies(avrcp_connection_t * connection){ + static uint32_t default_companies[] = { + 0x581900 //BT SIG registered CompanyID + }; + + uint8_t target_supported_companies_num = connection->target_supported_companies_num; + const uint32_t *target_supported_companies = connection->target_supported_companies; + + if (connection->target_supported_companies_num == 0){ + target_supported_companies_num = 1; + target_supported_companies = default_companies; + } + + uint16_t capabilities_size = target_supported_companies_num * 3; + + uint8_t status = avrcp_prepare_vendor_dependent_response_for_connection(connection, AVRCP_PDU_ID_GET_CAPABILITIES, 2 + capabilities_size); + if (status != ERROR_CODE_SUCCESS) return status; + + connection->cmd_operands[connection->cmd_operands_length++] = AVRCP_CAPABILITY_ID_COMPANY; + connection->cmd_operands[connection->cmd_operands_length++] = target_supported_companies_num; + + uint8_t i; + for (i = 0; i < target_supported_companies_num; i++){ + little_endian_store_24(connection->cmd_operands, connection->cmd_operands_length, target_supported_companies[i]); + connection->cmd_operands_length += 3; + } connection->state = AVCTP_W2_SEND_RESPONSE; avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid); return ERROR_CODE_SUCCESS; } -uint8_t avrcp_target_supported_events(uint16_t avrcp_cid, uint8_t num_event_ids, const uint8_t *event_ids, uint8_t event_ids_size){ - return avrcp_target_capability(avrcp_cid, AVRCP_CAPABILITY_ID_EVENT, num_event_ids, event_ids, event_ids_size); } -uint8_t avrcp_target_supported_companies(uint16_t avrcp_cid, uint8_t num_company_ids, const uint8_t *company_ids, uint8_t company_ids_size){ - return avrcp_target_capability(avrcp_cid, AVRCP_CAPABILITY_ID_COMPANY, num_company_ids, company_ids, company_ids_size); } uint8_t avrcp_target_play_status(uint16_t avrcp_cid, uint32_t song_length_ms, uint32_t song_position_ms, avrcp_playback_status_t play_status){ @@ -940,10 +981,10 @@ static void avrcp_handle_l2cap_data_packet_for_signaling_connection(avrcp_connec avrcp_capability_id_t capability_id = (avrcp_capability_id_t) packet[pos]; switch (capability_id){ case AVRCP_CAPABILITY_ID_EVENT: - avrcp_target_emit_respond_vendor_dependent_query(avrcp_target_context.avrcp_callback, connection->avrcp_cid, AVRCP_SUBEVENT_EVENT_IDS_QUERY); + avrcp_target_supported_events(connection); break; case AVRCP_CAPABILITY_ID_COMPANY: - avrcp_target_emit_respond_vendor_dependent_query(avrcp_target_context.avrcp_callback, connection->avrcp_cid, AVRCP_SUBEVENT_COMPANY_IDS_QUERY); + avrcp_target_supported_companies(connection); break; default: avrcp_target_response_reject(connection, subunit_type, subunit_id, opcode, pdu_id, AVRCP_STATUS_INVALID_PARAMETER); diff --git a/src/classic/avrcp_target.h b/src/classic/avrcp_target.h index 870b27c63..2c927ead0 100644 --- a/src/classic/avrcp_target.h +++ b/src/classic/avrcp_target.h @@ -100,7 +100,6 @@ void avrcp_target_register_set_addressed_player_handler(bool (*callback)(uint16_ * @param company_ids_size * @return status ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER if connection is not found, otherwise ERROR_CODE_SUCCESS */ -uint8_t avrcp_target_supported_companies(uint16_t avrcp_cid, uint8_t num_company_ids, const uint8_t *company_ids, uint8_t company_ids_size); /** * @brief Send a list of Events supported by target. @@ -111,7 +110,6 @@ uint8_t avrcp_target_supported_companies(uint16_t avrcp_cid, uint8_t num_company * @param event_ids_size * @return status ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER if connection is not found, otherwise ERROR_CODE_SUCCESS */ -uint8_t avrcp_target_supported_events(uint16_t avrcp_cid, uint8_t num_event_ids, const uint8_t *event_ids, uint8_t event_ids_size); /** * @brief Send a play status.