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 "vendor_packet.h"
18
19 #include <bluetooth/log.h>
20
21 #include "internal_include/bt_trace.h"
22
23 namespace bluetooth {
24 namespace avrcp {
25
MakeBuilder(CType ctype,CommandPdu pdu,PacketType packet_type,std::unique_ptr<::bluetooth::PacketBuilder> payload)26 std::unique_ptr<VendorPacketBuilder> VendorPacketBuilder::MakeBuilder(
27 CType ctype, CommandPdu pdu, PacketType packet_type,
28 std::unique_ptr<::bluetooth::PacketBuilder> payload) {
29 // If the payload size is greater than max uint16_t
30 // the packet should be fragmented
31 log::assert_that(payload->size() <= size_t(0xFFFF),
32 "payload size bigger than uint16_t");
33
34 std::unique_ptr<VendorPacketBuilder> builder(
35 new VendorPacketBuilder(ctype, pdu, packet_type));
36 builder->payload_ = std::move(payload);
37
38 return builder;
39 }
40
size() const41 size_t VendorPacketBuilder::size() const {
42 return VendorPacket::kMinSize() + payload_->size();
43 }
44
Serialize(const std::shared_ptr<::bluetooth::Packet> & pkt)45 bool VendorPacketBuilder::Serialize(
46 const std::shared_ptr<::bluetooth::Packet>& pkt) {
47 ReserveSpace(pkt, size());
48
49 // Push the standard avrcp headers
50 PacketBuilder::PushHeader(pkt);
51
52 // Push the avrcp vendor command headers
53 log::assert_that(payload_->size() < size_t(0xFFFF),
54 "payload size bigger than uint16_t");
55 PushHeader(pkt, payload_->size());
56
57 // Push the payload for the packet
58 return payload_->Serialize(pkt);
59 }
60
PushHeader(const std::shared_ptr<::bluetooth::Packet> & pkt,uint16_t parameter_length)61 void VendorPacketBuilder::PushHeader(
62 const std::shared_ptr<::bluetooth::Packet>& pkt,
63 uint16_t parameter_length) {
64 PushCompanyId(pkt, BLUETOOTH_COMPANY_ID);
65 AddPayloadOctets1(pkt, static_cast<uint8_t>(pdu_));
66 AddPayloadOctets1(pkt, static_cast<uint8_t>(packet_type_));
67 AddPayloadOctets2(pkt, base::ByteSwap(parameter_length));
68 }
69
PushAttributeValue(const std::shared_ptr<::bluetooth::Packet> & pkt,const AttributeEntry & entry)70 bool VendorPacketBuilder::PushAttributeValue(
71 const std::shared_ptr<::bluetooth::Packet>& pkt,
72 const AttributeEntry& entry) {
73 AddPayloadOctets4(pkt,
74 base::ByteSwap(static_cast<uint32_t>(entry.attribute())));
75 uint16_t character_set = 0x006a; // UTF-8
76 AddPayloadOctets2(pkt, base::ByteSwap(character_set));
77 uint16_t value_length = entry.value().length();
78 AddPayloadOctets2(pkt, base::ByteSwap(value_length));
79 for (int i = 0; i < value_length; i++) {
80 AddPayloadOctets1(pkt, entry.value()[i]);
81 }
82
83 return true;
84 }
85
GetCompanyId() const86 uint32_t VendorPacket::GetCompanyId() const {
87 return PullCompanyId(begin() + Packet::kMinSize());
88 }
89
GetCommandPdu() const90 CommandPdu VendorPacket::GetCommandPdu() const {
91 auto value = *(begin() + Packet::kMinSize() + static_cast<size_t>(3));
92 return static_cast<CommandPdu>(value);
93 }
94
GetPacketType() const95 PacketType VendorPacket::GetPacketType() const {
96 auto value = *(begin() + Packet::kMinSize() + static_cast<size_t>(4));
97 return static_cast<PacketType>(value);
98 }
99
GetParameterLength() const100 uint16_t VendorPacket::GetParameterLength() const {
101 auto it = begin() + Packet::kMinSize() + static_cast<size_t>(5);
102 // Swap to little endian
103 return it.extractBE<uint16_t>();
104 }
105
IsValid() const106 bool VendorPacket::IsValid() const {
107 if (size() < VendorPacket::kMinSize()) return false;
108
109 auto start = begin() + VendorPacket::kMinSize();
110 // Even if end is less than start and a sign extension occurs, thats fine as
111 // its pretty definitive proof that the packet is poorly formated
112 return GetParameterLength() == (end() - start);
113 }
114
ToString() const115 std::string VendorPacket::ToString() const {
116 std::stringstream ss;
117 ss << "VendorPacket: " << std::endl;
118 ss << " └ cType = " << GetCType() << std::endl;
119 ss << " └ Subunit Type = " << loghex(GetSubunitType()) << std::endl;
120 ss << " └ Subunit ID = " << loghex(GetSubunitId()) << std::endl;
121 ss << " └ OpCode = " << GetOpcode() << std::endl;
122 ss << " └ Company ID = " << loghex(GetCompanyId()) << std::endl;
123 ss << " └ Command PDU = " << GetCommandPdu() << std::endl;
124 ss << " └ PacketType = " << GetPacketType() << std::endl;
125 ss << " └ Parameter Length = " << loghex(GetParameterLength()) << std::endl;
126 ss << " └ Payload =";
127 for (auto it = begin(); it != end(); it++) {
128 ss << " " << loghex(*it);
129 }
130 ss << std::endl;
131 return ss.str();
132 }
133
134 } // namespace avrcp
135 } // namespace bluetooth
136