Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 747f36ad authored by Ajay Panicker's avatar Ajay Panicker
Browse files

Add packet classes needed for AVRCP Absolute Volume

Add the Register Notification Request packet as well as the
packets Set Absolute Volume packet.

Bug: 68854188
Test: run host native test net_test_packets
Change-Id: Ie0d1f1fb23254c1353b6a73529ca93e92f231ed5
parent 5b0cac46
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ cc_test {
        "tests/avrcp/pass_through_packet_test.cc",
        "tests/avrcp/play_item_packet_test.cc",
        "tests/avrcp/register_notification_packet_test.cc",
        "tests/avrcp/set_absolute_volume_packet_test.cc",
        "tests/avrcp/set_browsed_player_packet_test.cc",
        "tests/avrcp/vendor_packet_test.cc",
        "tests/base/iterator_test.cc",
+1 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@ cc_library_static {
        "pass_through_packet.cc",
        "play_item.cc",
        "register_notification_packet.cc",
        "set_absolute_volume.cc",
        "set_browsed_player.cc",
        "vendor_packet.cc",
    ],
+1 −0
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@ enum class CommandPdu : uint8_t {
  GET_ELEMENT_ATTRIBUTES = 0x20,
  GET_PLAY_STATUS = 0x30,
  REGISTER_NOTIFICATION = 0x31,
  SET_ABSOLUTE_VOLUME = 0x50,
  SET_ADDRESSED_PLAYER = 0x60,
  PLAY_ITEM = 0x74,
};
+113 −16
Original line number Diff line number Diff line
@@ -21,6 +21,54 @@
namespace bluetooth {
namespace avrcp {

bool RegisterNotificationResponse::IsInterim() const {
  return GetCType() == CType::INTERIM;
}

Event RegisterNotificationResponse::GetEvent() const {
  auto value = *(begin() + VendorPacket::kMinSize());
  return static_cast<Event>(value);
}

uint8_t RegisterNotificationResponse::GetVolume() const {
  CHECK(GetEvent() == Event::VOLUME_CHANGED);
  auto it = begin() + VendorPacket::kMinSize() + static_cast<size_t>(1);
  return *it;
}

bool RegisterNotificationResponse::IsValid() const {
  if (!VendorPacket::IsValid()) return false;
  if (size() < kMinSize()) return false;
  if (GetCType() != CType::INTERIM && GetCType() != CType::CHANGED)
    return false;

  switch (GetEvent()) {
    case Event::VOLUME_CHANGED:
      return size() == (kMinSize() + 1);
    default:
      // TODO (apanicke): Add the remaining events when implementing AVRCP
      // Controller
      return false;
  }
}

std::string RegisterNotificationResponse::ToString() const {
  std::stringstream ss;
  ss << "RegisterNotificationResponse: " << std::endl;
  ss << "  └ cType = " << GetCType() << std::endl;
  ss << "  └ Subunit Type = " << loghex(GetSubunitType()) << std::endl;
  ss << "  └ Subunit ID = " << loghex(GetSubunitId()) << std::endl;
  ss << "  └ OpCode = " << GetOpcode() << std::endl;
  ss << "  └ Company ID = " << loghex(GetCompanyId()) << std::endl;
  ss << "  └ Command PDU = " << GetCommandPdu() << std::endl;
  ss << "  └ PacketType = " << GetPacketType() << std::endl;
  ss << "  └ Parameter Length = " << loghex(GetParameterLength()) << std::endl;
  ss << "  └ Event Registered = " << GetEvent() << std::endl;
  ss << std::endl;

  return ss.str();
}

std::unique_ptr<RegisterNotificationResponseBuilder>
RegisterNotificationResponseBuilder::MakePlaybackStatusBuilder(
    bool interim, uint8_t play_status) {
@@ -124,22 +172,43 @@ bool RegisterNotificationResponseBuilder::Serialize(
  VendorPacketBuilder::PushHeader(pkt, 1 + data_size);

  AddPayloadOctets1(pkt, static_cast<uint8_t>(event_));
  if (event_ == Event::PLAYBACK_STATUS_CHANGED) {
  switch (event_) {
    case Event::PLAYBACK_STATUS_CHANGED: {
      uint8_t playback_status = data_ & 0xFF;
      AddPayloadOctets1(pkt, playback_status);
  } else if (event_ == Event::TRACK_CHANGED) {
      break;
    }
    case Event::TRACK_CHANGED: {
      AddPayloadOctets8(pkt, base::ByteSwap(data_));
  } else if (event_ == Event::PLAYBACK_POS_CHANGED) {
      break;
    }
    case Event::PLAYBACK_POS_CHANGED: {
      uint32_t playback_pos = data_ & 0xFFFFFFFF;
      AddPayloadOctets4(pkt, base::ByteSwap(playback_pos));
  } else if (event_ == Event::ADDRESSED_PLAYER_CHANGED) {
      break;
    }
    case Event::PLAYER_APPLICATION_SETTING_CHANGED:
      break;  // No additional data
    case Event::NOW_PLAYING_CONTENT_CHANGED:
      break;  // No additional data
    case Event::AVAILABLE_PLAYERS_CHANGED:
      break;  // No additional data
    case Event::ADDRESSED_PLAYER_CHANGED: {
      uint16_t uid_counter = data_ & 0xFFFF;
      uint16_t player_id = (data_ >> 16) & 0xFFFF;
      AddPayloadOctets2(pkt, base::ByteSwap(player_id));
      AddPayloadOctets2(pkt, base::ByteSwap(uid_counter));
  } else if (event_ == Event::UIDS_CHANGED) {
      break;
    }
    case Event::UIDS_CHANGED: {
      uint16_t uid_counter = data_ & 0xFFFF;
      AddPayloadOctets2(pkt, base::ByteSwap(uid_counter));
      break;
    }
    default:
      // TODO (apanicke): Add Volume Changed builder for when we are controller.
      LOG(FATAL) << "Unhandled event for register notification";
      break;
  }

  return true;
@@ -177,5 +246,33 @@ std::string RegisterNotificationRequest::ToString() const {
  return ss.str();
}

std::unique_ptr<RegisterNotificationRequestBuilder>
RegisterNotificationRequestBuilder::MakeBuilder(Event event,
                                                uint32_t interval) {
  std::unique_ptr<RegisterNotificationRequestBuilder> builder(
      new RegisterNotificationRequestBuilder(event, interval));

  return builder;
}

size_t RegisterNotificationRequestBuilder::size() const {
  return RegisterNotificationRequest::kMinSize();
}

bool RegisterNotificationRequestBuilder::Serialize(
    const std::shared_ptr<::bluetooth::Packet>& pkt) {
  ReserveSpace(pkt, size());

  PacketBuilder::PushHeader(pkt);

  VendorPacketBuilder::PushHeader(pkt, size() - VendorPacket::kMinSize());

  AddPayloadOctets1(pkt, static_cast<uint8_t>(event_));

  AddPayloadOctets4(pkt, base::ByteSwap(interval_));

  return true;
}

}  // namespace avrcp
}  // namespace bluetooth
 No newline at end of file
+58 −3
Original line number Diff line number Diff line
@@ -21,17 +21,50 @@
namespace bluetooth {
namespace avrcp {

class RegisterNotificationResponse : public VendorPacket {
 public:
  virtual ~RegisterNotificationResponse() = default;

  /**
   *  Register Notificaiton Request Packet Layout
   *   AvrcpPacket:
   *     CType c_type_;
   *     uint8_t subunit_type_ : 5;
   *     uint8_t subunit_id_ : 3;
   *     Opcode opcode_;
   *   VendorPacket:
   *     uint8_t company_id[3];
   *     uint8_t command_pdu;
   *     uint8_t packet_type;
   *     uint16_t param_length;
   *   RegisterNotificationRequestPacket:
   *     uint8_t event_id;
   *     uint8_t[] data;  // Length changes based on the event_id
   */
  static constexpr size_t kMinSize() { return VendorPacket::kMinSize() + 1; }

  // TODO (apanicke): Add other getters when implementing AVRCP Controller
  bool IsInterim() const;
  Event GetEvent() const;
  uint8_t GetVolume() const;

  virtual bool IsValid() const override;
  virtual std::string ToString() const override;

 protected:
  using VendorPacket::VendorPacket;
};

class RegisterNotificationResponseBuilder : public VendorPacketBuilder {
 public:
  virtual ~RegisterNotificationResponseBuilder() = default;

  // Playback Status Changed Maker
  static std::unique_ptr<RegisterNotificationResponseBuilder>
  MakePlaybackStatusBuilder(bool interim, uint8_t play_status);
  // Track Changed Maker

  static std::unique_ptr<RegisterNotificationResponseBuilder>
  MakeTrackChangedBuilder(bool interim, uint64_t track_uid);
  // Playback Position Changed Maker

  static std::unique_ptr<RegisterNotificationResponseBuilder>
  MakePlaybackPositionBuilder(bool interim, uint32_t playback_pos);

@@ -97,5 +130,27 @@ class RegisterNotificationRequest : public VendorPacket {
  using VendorPacket::VendorPacket;
};

class RegisterNotificationRequestBuilder : public VendorPacketBuilder {
 public:
  virtual ~RegisterNotificationRequestBuilder() = default;

  static std::unique_ptr<RegisterNotificationRequestBuilder> MakeBuilder(
      Event event, uint32_t interval);

  virtual size_t size() const override;
  virtual bool Serialize(
      const std::shared_ptr<::bluetooth::Packet>& pkt) override;

 protected:
  Event event_;
  uint32_t interval_;

  RegisterNotificationRequestBuilder(Event event, uint32_t interval)
      : VendorPacketBuilder(CType::NOTIFY, CommandPdu::REGISTER_NOTIFICATION,
                            PacketType::SINGLE),
        event_(event),
        interval_(interval){};
};

}  // namespace avrcp
}  // namespace bluetooth
 No newline at end of file
Loading