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