Home | History | Annotate | Download | only in avrcp
      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