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 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 37 size_t VendorPacketBuilder::size() const { 38 return VendorPacket::kMinSize() + payload_->size(); 39 } 40 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 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 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 82 uint32_t VendorPacket::GetCompanyId() const { 83 return PullCompanyId(begin() + Packet::kMinSize()); 84 } 85 86 CommandPdu VendorPacket::GetCommandPdu() const { 87 auto value = *(begin() + Packet::kMinSize() + static_cast<size_t>(3)); 88 return static_cast<CommandPdu>(value); 89 } 90 91 PacketType VendorPacket::GetPacketType() const { 92 auto value = *(begin() + Packet::kMinSize() + static_cast<size_t>(4)); 93 return static_cast<PacketType>(value); 94 } 95 96 uint16_t VendorPacket::GetParameterLength() const { 97 auto it = begin() + Packet::kMinSize() + static_cast<size_t>(5); 98 // Swap to little endian 99 return base::ByteSwap(it.extract<uint16_t>()); 100 } 101 102 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 111 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