@@ 1,4 1,4 @@
-// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "AVRCP.hpp"
@@ 10,28 10,28 @@
namespace bluetooth
{
-
AVRCP::PlaybackStatusInfo AVRCP::playInfo;
int AVRCP::currentTrackIndex;
MediaContext AVRCP::mediaTracker;
- std::array<uint8_t, 200> AVRCP::sdpTargetServiceBuffer;
- std::array<uint8_t, 200> AVRCP::sdpControllerServiceBuffer;
+ std::array<std::uint8_t, AVRCP::SDP_BUFFER_LENGTH> AVRCP::sdpTargetServiceBuffer;
+ std::array<std::uint8_t, AVRCP::SDP_BUFFER_LENGTH> AVRCP::sdpControllerServiceBuffer;
sys::Service *AVRCP::ownerService = nullptr;
- void AVRCP::packetHandler(uint8_t packetType, uint16_t channel, uint8_t *packet, uint16_t size)
+ void AVRCP::packetHandler(uint8_t packetType,
+ [[maybe_unused]] uint16_t channel,
+ uint8_t *packet,
+ [[maybe_unused]] uint16_t size)
{
bd_addr_t event_addr;
- uint16_t local_cid;
- uint8_t status = ERROR_CODE_SUCCESS;
+ std::uint16_t local_cid;
+ std::uint8_t status = ERROR_CODE_SUCCESS;
- if (packetType != HCI_EVENT_PACKET) {
- return;
- }
- if (hci_event_packet_get_type(packet) != HCI_EVENT_AVRCP_META) {
+ if (packetType != HCI_EVENT_PACKET || hci_event_packet_get_type(packet) != HCI_EVENT_AVRCP_META) {
return;
}
- switch (packet[2]) {
+ const auto subevent_code = hci_event_avrcp_meta_get_subevent_code(packet);
+ switch (subevent_code) {
case AVRCP_SUBEVENT_CONNECTION_ESTABLISHED:
local_cid = avrcp_subevent_connection_established_get_avrcp_cid(packet);
status = avrcp_subevent_connection_established_get_status(packet);
@@ 46,13 46,15 @@ namespace bluetooth
avrcp_target_support_event(AVRCP::mediaTracker.avrcp_cid, AVRCP_NOTIFICATION_EVENT_TRACK_CHANGED);
avrcp_target_support_event(AVRCP::mediaTracker.avrcp_cid,
AVRCP_NOTIFICATION_EVENT_NOW_PLAYING_CONTENT_CHANGED);
+ avrcp_controller_enable_notification(AVRCP::mediaTracker.avrcp_cid,
+ AVRCP_NOTIFICATION_EVENT_VOLUME_CHANGED);
avrcp_target_set_now_playing_info(
AVRCP::mediaTracker.avrcp_cid, NULL, sizeof(AVRCP::tracks) / sizeof(avrcp_track_t));
avrcp_target_set_unit_info(AVRCP::mediaTracker.avrcp_cid, AVRCP_SUBUNIT_TYPE_AUDIO, AVRCP::companyId);
avrcp_target_set_subunit_info(AVRCP::mediaTracker.avrcp_cid,
AVRCP_SUBUNIT_TYPE_AUDIO,
- (uint8_t *)AVRCP::subunitInfo,
+ static_cast<const std::uint8_t *>(AVRCP::subunitInfo),
sizeof(AVRCP::subunitInfo));
return;
@@ 66,7 68,7 @@ namespace bluetooth
}
if (status != ERROR_CODE_SUCCESS) {
- LOG_INFO("Responding to event 0x%02x failed with status 0x%02x\n", packet[2], status);
+ LOG_INFO("Responding to event 0x%02x failed with status 0x%02x\n", subevent_code, status);
}
}
@@ 75,20 77,18 @@ namespace bluetooth
uint8_t *packet,
[[maybe_unused]] uint16_t size)
{
- uint8_t status = ERROR_CODE_SUCCESS;
+ std::uint8_t status = ERROR_CODE_SUCCESS;
- if (packetType != HCI_EVENT_PACKET) {
- return;
- }
- if (hci_event_packet_get_type(packet) != HCI_EVENT_AVRCP_META) {
+ if (packetType != HCI_EVENT_PACKET || hci_event_packet_get_type(packet) != HCI_EVENT_AVRCP_META) {
return;
}
- switch (packet[2]) {
+ const auto subevent_code = hci_event_avrcp_meta_get_subevent_code(packet);
+ switch (subevent_code) {
case AVRCP_SUBEVENT_NOTIFICATION_VOLUME_CHANGED:
AVRCP::mediaTracker.volume = avrcp_subevent_notification_volume_changed_get_absolute_volume(packet);
- LOG_INFO("AVRCP Target: Volume set to %d%% (%d)\n",
- AVRCP::mediaTracker.volume * 127 / 100,
+ LOG_INFO("AVRCP Target: Volume set to %u%% (%u)\n",
+ AVRCP::targetVolumeToPercent(AVRCP::mediaTracker.volume),
AVRCP::mediaTracker.volume);
break;
case AVRCP_SUBEVENT_PLAY_STATUS_QUERY:
@@ 98,7 98,8 @@ namespace bluetooth
AVRCP::playInfo.status);
break;
case AVRCP_SUBEVENT_OPERATION: {
- auto operation_id = (avrcp_operation_id_t)avrcp_subevent_operation_get_operation_id(packet);
+ const auto operation_id =
+ static_cast<avrcp_operation_id_t>(avrcp_subevent_operation_get_operation_id(packet));
switch (operation_id) {
case AVRCP_OPERATION_ID_PLAY: {
LOG_INFO("AVRCP Target: PLAY\n");
@@ 128,41 129,41 @@ namespace bluetooth
}
if (status != ERROR_CODE_SUCCESS) {
- LOG_INFO("Responding to event 0x%02x failed with status 0x%02x\n", packet[2], status);
+ LOG_INFO("Responding to event 0x%02x failed with status 0x%02x\n", subevent_code, status);
}
}
void AVRCP::controllerPacketHandler(uint8_t packetType,
[[maybe_unused]] uint16_t channel,
- [[maybe_unused]] uint8_t *packet,
- uint16_t size)
+ uint8_t *packet,
+ [[maybe_unused]] uint16_t size)
{
- uint8_t status = 0xFF;
-
- if (packetType != HCI_EVENT_PACKET) {
- return;
- }
- if (hci_event_packet_get_type(packet) != HCI_EVENT_AVRCP_META) {
+ if (packetType != HCI_EVENT_PACKET || hci_event_packet_get_type(packet) != HCI_EVENT_AVRCP_META) {
return;
}
- status = packet[5];
if (AVRCP::mediaTracker.avrcp_cid == 0u) {
return;
}
+ const std::uint8_t status = packet[5];
+
// ignore INTERIM status
if (status == AVRCP_CTYPE_RESPONSE_INTERIM) {
return;
}
- switch (packet[2]) {
+ const auto subevent_code = hci_event_avrcp_meta_get_subevent_code(packet);
+ switch (subevent_code) {
case AVRCP_SUBEVENT_NOTIFICATION_VOLUME_CHANGED: {
const auto volume = avrcp_subevent_notification_volume_changed_get_absolute_volume(packet);
auto &busProxy = AVRCP::ownerService->bus;
busProxy.sendUnicast(std::make_shared<message::bluetooth::A2DPVolume>(volume), service::name::bluetooth);
- LOG_INFO("AVRCP Controller: notification absolute volume changed %d %%\n", volume * 100 / 127);
+ LOG_INFO("AVRCP Controller: notification absolute volume changed %u%% (%u)\n",
+ AVRCP::controllerVolumeToPercent(volume),
+ volume);
} break;
+
case AVRCP_SUBEVENT_NOTIFICATION_EVENT_BATT_STATUS_CHANGED:
// see avrcp_battery_status_t
LOG_INFO("AVRCP Controller: Notification Battery Status %d\n",
@@ 191,4 192,14 @@ namespace bluetooth
avrcp_controller_register_packet_handler(&controllerPacketHandler);
}
+ std::uint16_t AVRCP::targetVolumeToPercent(std::uint16_t volume)
+ {
+ return volume * 127 / 100;
+ }
+
+ std::uint16_t AVRCP::controllerVolumeToPercent(std::uint16_t volume)
+ {
+ return volume * 100 / 127;
+ }
+
} // namespace bluetooth
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 19,22 19,14 @@ namespace bluetooth
{
class AVRCP
{
- public:
- constexpr static const uint8_t subunitInfo[] = {0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
- 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7};
- constexpr static uint32_t companyId = 0x112233;
- constexpr static uint8_t companiesNum = 1;
- constexpr static uint8_t companies[] = {
- 0x00, 0x19, 0x58 // BT SIG registered CompanyID
- };
+ private:
+ static std::uint16_t targetVolumeToPercent(std::uint16_t volume);
+ static std::uint16_t controllerVolumeToPercent(std::uint16_t volume);
- constexpr static uint8_t eventsNum = 6;
- constexpr 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};
+ public:
+ static constexpr uint8_t subunitInfo[] = {0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
+ 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7};
+ static constexpr uint32_t companyId = 0x112233;
static constexpr int SDP_BUFFER_LENGTH = 200;
struct PlaybackStatusInfo
{
@@ 44,8 36,8 @@ namespace bluetooth
uint32_t song_position_ms; // 0xFFFFFFFF if not supported
};
- static std::array<uint8_t, SDP_BUFFER_LENGTH> sdpTargetServiceBuffer;
- static std::array<uint8_t, SDP_BUFFER_LENGTH> sdpControllerServiceBuffer;
+ static std::array<std::uint8_t, SDP_BUFFER_LENGTH> sdpTargetServiceBuffer;
+ static std::array<std::uint8_t, SDP_BUFFER_LENGTH> sdpControllerServiceBuffer;
static sys::Service *ownerService;
static avrcp_track_t tracks[3];