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