/* * Copyright 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "capabilities_packet.h" namespace bluetooth { namespace avrcp { std::unique_ptr GetCapabilitiesRequestBuilder::MakeBuilder(Capability capability) { std::unique_ptr builder( new GetCapabilitiesRequestBuilder(capability)); return builder; } size_t GetCapabilitiesRequestBuilder::size() const { return GetCapabilitiesRequest::kMinSize(); } bool GetCapabilitiesRequestBuilder::Serialize( const std::shared_ptr<::bluetooth::Packet>& pkt) { ReserveSpace(pkt, size()); // Push the standard avrcp headers PacketBuilder::PushHeader(pkt); // Push the avrcp vendor command headers, the parameter length is always 1 VendorPacketBuilder::PushHeader(pkt, 1); // Push the capability return AddPayloadOctets1(pkt, static_cast(capability_)); } Capability GetCapabilitiesRequest::GetCapabilityRequested() const { auto value = *(begin() + VendorPacket::kMinSize()); return static_cast(value); } bool GetCapabilitiesRequest::IsValid() const { if (!VendorPacket::IsValid()) return false; return (size() == VendorPacket::kMinSize() + 1); } std::string GetCapabilitiesRequest::ToString() const { std::stringstream ss; ss << "AvrcpCapabilityReqPacket: " << std::endl; ss << " └ cType = " << GetCType() << std::endl; ss << " └ Subunit Type = " << loghex(GetSubunitType()) << std::endl; ss << " └ Subunit ID = " << loghex(GetSubunitId()) << std::endl; ss << " └ OpCode = " << GetOpcode() << std::endl; ss << " └ Company ID = " << loghex(GetCompanyId()) << std::endl; ss << " └ Command PDU = " << GetCommandPdu() << std::endl; ss << " └ PacketType = " << GetPacketType() << std::endl; ss << " └ Parameter Length = " << loghex(GetParameterLength()) << std::endl; ss << " └ Capabilities Request = " << GetCapabilityRequested() << std::endl; return ss.str(); } std::unique_ptr GetCapabilitiesResponseBuilder::MakeCompanyIdBuilder( uint32_t company_id_element) { std::unique_ptr builder( new GetCapabilitiesResponseBuilder(Capability::COMPANY_ID)); company_id_element &= 0x00FFFFFF; builder->elements_.insert(company_id_element); return builder; } std::unique_ptr GetCapabilitiesResponseBuilder::MakeEventsSupportedBuilder(Event event) { std::unique_ptr builder( new GetCapabilitiesResponseBuilder(Capability::EVENTS_SUPPORTED)); builder->elements_.insert(static_cast(event)); return builder; } GetCapabilitiesResponseBuilder* GetCapabilitiesResponseBuilder::AddCompanyId( uint32_t company_id) { CHECK_EQ(capability_, Capability::COMPANY_ID); CHECK_LT(elements_.size(), size_t(0xFF)) << __func__ << ": maximum capability count reached"; company_id &= 0x00FFFFFF; elements_.insert(company_id); return this; } GetCapabilitiesResponseBuilder* GetCapabilitiesResponseBuilder::AddEvent( Event event) { CHECK_EQ(capability_, Capability::EVENTS_SUPPORTED); CHECK_LT(elements_.size(), size_t(0xFF)) << __func__ << ": maximum capability count reached"; elements_.insert(static_cast(event)); return this; } size_t GetCapabilitiesResponseBuilder::size() const { // Company ID's have a size of 3 while Events have a size of 1 size_t capability_count = elements_.size(); size_t capability_size = capability_ == Capability::COMPANY_ID ? 3 : 1; return GetCapabilitiesResponse::kMinSize() + (capability_count * capability_size); } bool GetCapabilitiesResponseBuilder::Serialize( const std::shared_ptr<::bluetooth::Packet>& pkt) { ReserveSpace(pkt, size()); // Push the standard avrcp headers PacketBuilder::PushHeader(pkt); // Push the avrcp vendor command headers uint16_t parameter_count = size() - VendorPacket::kMinSize(); VendorPacketBuilder::PushHeader(pkt, parameter_count); // Push the capability, capability count, and elements AddPayloadOctets1(pkt, static_cast(capability_)); AddPayloadOctets1(pkt, elements_.size()); for (auto it = elements_.begin(); it != elements_.end(); it++) { if (capability_ == Capability::COMPANY_ID) PushCompanyId(pkt, *it); else AddPayloadOctets1(pkt, *it); } return true; } } // namespace avrcp } // namespace bluetooth