1 /*
2 * Copyright 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "get_element_attributes_packet.h"
18
19 #include <bluetooth/log.h>
20
21 #include <algorithm>
22
23 namespace bluetooth {
24 namespace avrcp {
25
GetIdentifier() const26 uint64_t GetElementAttributesRequest::GetIdentifier() const {
27 auto it = begin() + VendorPacket::kMinSize();
28 return it.extract<uint64_t>();
29 }
30
GetNumAttributes() const31 uint8_t GetElementAttributesRequest::GetNumAttributes() const {
32 auto it = begin() + VendorPacket::kMinSize() + static_cast<size_t>(8);
33 return it.extract<uint8_t>();
34 }
35
GetAttributesRequested() const36 std::vector<Attribute> GetElementAttributesRequest::GetAttributesRequested()
37 const {
38 auto it = begin() + VendorPacket::kMinSize() + static_cast<size_t>(8);
39
40 size_t number_of_attributes = it.extract<uint8_t>();
41
42 std::vector<Attribute> attribute_list;
43
44 for (size_t i = 0; i < number_of_attributes; i++) {
45 attribute_list.push_back((Attribute)it.extractBE<uint32_t>());
46 }
47
48 return attribute_list;
49 }
50
IsValid() const51 bool GetElementAttributesRequest::IsValid() const {
52 if (!VendorPacket::IsValid()) return false;
53 if (size() < kMinSize()) return false;
54
55 size_t num_attributes = GetNumAttributes();
56 auto attr_start = begin() + VendorPacket::kMinSize() + static_cast<size_t>(9);
57
58 // Casting the int returned from end - attr_start should be fine. If an
59 // overflow occurs we can definitly say the packet is invalid
60 return (num_attributes * sizeof(Attribute)) == (size_t)(end() - attr_start);
61 }
62
ToString() const63 std::string GetElementAttributesRequest::ToString() const {
64 std::stringstream ss;
65 ss << "RegisterNotificationPacket: " << std::endl;
66 ss << " └ cType = " << GetCType() << std::endl;
67 ss << " └ Subunit Type = " << loghex(GetSubunitType()) << std::endl;
68 ss << " └ Subunit ID = " << loghex(GetSubunitId()) << std::endl;
69 ss << " └ OpCode = " << GetOpcode() << std::endl;
70 ss << " └ Company ID = " << loghex(GetCompanyId()) << std::endl;
71 ss << " └ Command PDU = " << GetCommandPdu() << std::endl;
72 ss << " └ PacketType = " << GetPacketType() << std::endl;
73 ss << " └ Parameter Length = " << GetParameterLength() << std::endl;
74 ss << " └ Identifier = " << loghex(GetIdentifier()) << std::endl;
75
76 auto attr_list = GetAttributesRequested();
77
78 ss << " └ Attribute List: Size: " << attr_list.size() << std::endl;
79 for (auto it = attr_list.begin(); it != attr_list.end(); it++) {
80 ss << " └ " << loghex((uint32_t)(*it)) << std::endl;
81 }
82 ss << std::endl;
83
84 return ss.str();
85 }
86
87 std::unique_ptr<GetElementAttributesResponseBuilder>
MakeBuilder(size_t mtu)88 GetElementAttributesResponseBuilder::MakeBuilder(size_t mtu) {
89 std::unique_ptr<GetElementAttributesResponseBuilder> builder(
90 new GetElementAttributesResponseBuilder(mtu));
91
92 return builder;
93 }
94
AddAttributeEntry(AttributeEntry entry)95 size_t GetElementAttributesResponseBuilder::AddAttributeEntry(
96 AttributeEntry entry) {
97 log::assert_that(entries_.size() < size_t(0xFF), "attribute entry overflow");
98
99 size_t remaining_space = mtu_ - size();
100 if (entry.size() > remaining_space) {
101 entry.resize(remaining_space);
102 }
103
104 if (entry.empty()) {
105 return 0;
106 }
107
108 entries_.insert(entry);
109 return entry.size();
110 }
111
AddAttributeEntry(Attribute attribute,const std::string & value)112 size_t GetElementAttributesResponseBuilder::AddAttributeEntry(
113 Attribute attribute, const std::string& value) {
114 return AddAttributeEntry(AttributeEntry(attribute, value));
115 }
116
size() const117 size_t GetElementAttributesResponseBuilder::size() const {
118 size_t attr_list_size = 0;
119
120 for (auto& attribute_entry : entries_) {
121 attr_list_size += attribute_entry.size();
122 }
123
124 return kHeaderSize() + attr_list_size;
125 }
126
Serialize(const std::shared_ptr<::bluetooth::Packet> & pkt)127 bool GetElementAttributesResponseBuilder::Serialize(
128 const std::shared_ptr<::bluetooth::Packet>& pkt) {
129 ReserveSpace(pkt, size());
130
131 PacketBuilder::PushHeader(pkt);
132
133 VendorPacketBuilder::PushHeader(pkt, size() - VendorPacket::kMinSize());
134
135 AddPayloadOctets1(pkt, entries_.size());
136 for (const auto& attribute_entry : entries_) {
137 PushAttributeValue(pkt, attribute_entry);
138 }
139
140 return true;
141 }
142
143 } // namespace avrcp
144 } // namespace bluetooth
145