1341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker/*
2341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker * Copyright 2018 The Android Open Source Project
3341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker *
4341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker * Licensed under the Apache License, Version 2.0 (the "License");
5341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker * you may not use this file except in compliance with the License.
6341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker * You may obtain a copy of the License at
7341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker *
8341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker *      http://www.apache.org/licenses/LICENSE-2.0
9341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker *
10341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker * Unless required by applicable law or agreed to in writing, software
11341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker * distributed under the License is distributed on an "AS IS" BASIS,
12341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker * See the License for the specific language governing permissions and
14341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker * limitations under the License.
15341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker */
16341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker
17341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker#include "capabilities_packet.h"
18341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker
19341ab2befa059e859cdc67655d83bac14980ea9eAjay Panickernamespace bluetooth {
20341ab2befa059e859cdc67655d83bac14980ea9eAjay Panickernamespace avrcp {
21341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker
22341ab2befa059e859cdc67655d83bac14980ea9eAjay Panickerstd::unique_ptr<GetCapabilitiesRequestBuilder>
23341ab2befa059e859cdc67655d83bac14980ea9eAjay PanickerGetCapabilitiesRequestBuilder::MakeBuilder(Capability capability) {
24341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  std::unique_ptr<GetCapabilitiesRequestBuilder> builder(
25341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker      new GetCapabilitiesRequestBuilder(capability));
26341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker
27341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  return builder;
28341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker}
29341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker
30341ab2befa059e859cdc67655d83bac14980ea9eAjay Panickersize_t GetCapabilitiesRequestBuilder::size() const {
318f7377353db29efe0a506123deec03d70935957aAjay Panicker  return GetCapabilitiesRequest::kMinSize();
32341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker}
33341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker
34341ab2befa059e859cdc67655d83bac14980ea9eAjay Panickerbool GetCapabilitiesRequestBuilder::Serialize(
35341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker    const std::shared_ptr<::bluetooth::Packet>& pkt) {
36341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  ReserveSpace(pkt, size());
37341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker
38341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  // Push the standard avrcp headers
39341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  PacketBuilder::PushHeader(pkt);
40341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker
41341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  // Push the avrcp vendor command headers, the parameter length is always 1
42341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  VendorPacketBuilder::PushHeader(pkt, 1);
43341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker
44341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  // Push the capability
45341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  return AddPayloadOctets1(pkt, static_cast<uint8_t>(capability_));
46341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker}
47341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker
48341ab2befa059e859cdc67655d83bac14980ea9eAjay PanickerCapability GetCapabilitiesRequest::GetCapabilityRequested() const {
498f7377353db29efe0a506123deec03d70935957aAjay Panicker  auto value = *(begin() + VendorPacket::kMinSize());
50341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  return static_cast<Capability>(value);
51341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker}
52341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker
53341ab2befa059e859cdc67655d83bac14980ea9eAjay Panickerbool GetCapabilitiesRequest::IsValid() const {
54341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  if (!VendorPacket::IsValid()) return false;
558f7377353db29efe0a506123deec03d70935957aAjay Panicker  return (size() == VendorPacket::kMinSize() + 1);
56341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker}
57341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker
58341ab2befa059e859cdc67655d83bac14980ea9eAjay Panickerstd::string GetCapabilitiesRequest::ToString() const {
59341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  std::stringstream ss;
60341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  ss << "AvrcpCapabilityReqPacket: " << std::endl;
61341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  ss << "  └ cType = " << GetCType() << std::endl;
62341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  ss << "  └ Subunit Type = " << loghex(GetSubunitType()) << std::endl;
63341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  ss << "  └ Subunit ID = " << loghex(GetSubunitId()) << std::endl;
64341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  ss << "  └ OpCode = " << GetOpcode() << std::endl;
65341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  ss << "  └ Company ID = " << loghex(GetCompanyId()) << std::endl;
66341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  ss << "  └ Command PDU = " << GetCommandPdu() << std::endl;
67341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  ss << "  └ PacketType = " << GetPacketType() << std::endl;
68341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  ss << "  └ Parameter Length = " << loghex(GetParameterLength()) << std::endl;
69341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  ss << "  └ Capabilities Request = " << GetCapabilityRequested() << std::endl;
70341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  return ss.str();
71341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker}
72341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker
73341ab2befa059e859cdc67655d83bac14980ea9eAjay Panickerstd::unique_ptr<GetCapabilitiesResponseBuilder>
74341ab2befa059e859cdc67655d83bac14980ea9eAjay PanickerGetCapabilitiesResponseBuilder::MakeCompanyIdBuilder(
75341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker    uint32_t company_id_element) {
76341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  std::unique_ptr<GetCapabilitiesResponseBuilder> builder(
77341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker      new GetCapabilitiesResponseBuilder(Capability::COMPANY_ID));
78341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker
79341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  company_id_element &= 0x00FFFFFF;
80341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  builder->elements_.insert(company_id_element);
81341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker
82341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  return builder;
83341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker}
84341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker
85341ab2befa059e859cdc67655d83bac14980ea9eAjay Panickerstd::unique_ptr<GetCapabilitiesResponseBuilder>
86341ab2befa059e859cdc67655d83bac14980ea9eAjay PanickerGetCapabilitiesResponseBuilder::MakeEventsSupportedBuilder(Event event) {
87341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  std::unique_ptr<GetCapabilitiesResponseBuilder> builder(
88341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker      new GetCapabilitiesResponseBuilder(Capability::EVENTS_SUPPORTED));
89341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker
90341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  builder->elements_.insert(static_cast<uint8_t>(event));
91341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker
92341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  return builder;
93341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker}
94341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker
95341ab2befa059e859cdc67655d83bac14980ea9eAjay PanickerGetCapabilitiesResponseBuilder* GetCapabilitiesResponseBuilder::AddCompanyId(
96341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker    uint32_t company_id) {
97341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  CHECK_EQ(capability_, Capability::COMPANY_ID);
98341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  CHECK_LT(elements_.size(), size_t(0xFF))
99341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker      << __func__ << ": maximum capability count reached";
100341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker
101341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  company_id &= 0x00FFFFFF;
102341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  elements_.insert(company_id);
103341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker
104341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  return this;
105341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker}
106341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker
107341ab2befa059e859cdc67655d83bac14980ea9eAjay PanickerGetCapabilitiesResponseBuilder* GetCapabilitiesResponseBuilder::AddEvent(
108341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker    Event event) {
109341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  CHECK_EQ(capability_, Capability::EVENTS_SUPPORTED);
110341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  CHECK_LT(elements_.size(), size_t(0xFF))
111341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker      << __func__ << ": maximum capability count reached";
112341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker
113341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  elements_.insert(static_cast<uint8_t>(event));
114341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker
115341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  return this;
116341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker}
117341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker
118341ab2befa059e859cdc67655d83bac14980ea9eAjay Panickersize_t GetCapabilitiesResponseBuilder::size() const {
119341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  // Company ID's have a size of 3 while Events have a size of 1
120341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  size_t capability_count = elements_.size();
121341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  size_t capability_size = capability_ == Capability::COMPANY_ID ? 3 : 1;
122341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker
1238f7377353db29efe0a506123deec03d70935957aAjay Panicker  return GetCapabilitiesResponse::kMinSize() +
124341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker         (capability_count * capability_size);
125341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker}
126341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker
127341ab2befa059e859cdc67655d83bac14980ea9eAjay Panickerbool GetCapabilitiesResponseBuilder::Serialize(
128341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker    const std::shared_ptr<::bluetooth::Packet>& pkt) {
129341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  ReserveSpace(pkt, size());
130341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker
131341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  // Push the standard avrcp headers
132341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  PacketBuilder::PushHeader(pkt);
133341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker
134341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  // Push the avrcp vendor command headers
1358f7377353db29efe0a506123deec03d70935957aAjay Panicker  uint16_t parameter_count = size() - VendorPacket::kMinSize();
136341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  VendorPacketBuilder::PushHeader(pkt, parameter_count);
137341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker
138341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  // Push the capability, capability count, and elements
139341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  AddPayloadOctets1(pkt, static_cast<uint8_t>(capability_));
140341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  AddPayloadOctets1(pkt, elements_.size());
141341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  for (auto it = elements_.begin(); it != elements_.end(); it++) {
142341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker    if (capability_ == Capability::COMPANY_ID)
143341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker      PushCompanyId(pkt, *it);
144341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker    else
145341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker      AddPayloadOctets1(pkt, *it);
146341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  }
147341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker
148341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  return true;
149341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker}
150341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker
151341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker}  // namespace avrcp
152341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker}  // namespace bluetooth