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