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 <base/logging.h>
     18 
     19 #include "register_notification_packet.h"
     20 
     21 namespace bluetooth {
     22 namespace avrcp {
     23 
     24 bool RegisterNotificationResponse::IsInterim() const {
     25   return GetCType() == CType::INTERIM;
     26 }
     27 
     28 Event RegisterNotificationResponse::GetEvent() const {
     29   auto value = *(begin() + VendorPacket::kMinSize());
     30   return static_cast<Event>(value);
     31 }
     32 
     33 uint8_t RegisterNotificationResponse::GetVolume() const {
     34   CHECK(GetEvent() == Event::VOLUME_CHANGED);
     35   auto it = begin() + VendorPacket::kMinSize() + static_cast<size_t>(1);
     36   return *it;
     37 }
     38 
     39 bool RegisterNotificationResponse::IsValid() const {
     40   if (!VendorPacket::IsValid()) return false;
     41   if (size() < kMinSize()) return false;
     42   if (GetCType() != CType::INTERIM && GetCType() != CType::CHANGED)
     43     return false;
     44 
     45   switch (GetEvent()) {
     46     case Event::VOLUME_CHANGED:
     47       return size() == (kMinSize() + 1);
     48     default:
     49       // TODO (apanicke): Add the remaining events when implementing AVRCP
     50       // Controller
     51       return false;
     52   }
     53 }
     54 
     55 std::string RegisterNotificationResponse::ToString() const {
     56   std::stringstream ss;
     57   ss << "RegisterNotificationResponse: " << std::endl;
     58   ss << "   cType = " << GetCType() << std::endl;
     59   ss << "   Subunit Type = " << loghex(GetSubunitType()) << std::endl;
     60   ss << "   Subunit ID = " << loghex(GetSubunitId()) << std::endl;
     61   ss << "   OpCode = " << GetOpcode() << std::endl;
     62   ss << "   Company ID = " << loghex(GetCompanyId()) << std::endl;
     63   ss << "   Command PDU = " << GetCommandPdu() << std::endl;
     64   ss << "   PacketType = " << GetPacketType() << std::endl;
     65   ss << "   Parameter Length = " << loghex(GetParameterLength()) << std::endl;
     66   ss << "   Event Registered = " << GetEvent() << std::endl;
     67   ss << std::endl;
     68 
     69   return ss.str();
     70 }
     71 
     72 std::unique_ptr<RegisterNotificationResponseBuilder>
     73 RegisterNotificationResponseBuilder::MakePlaybackStatusBuilder(
     74     bool interim, uint8_t play_status) {
     75   std::unique_ptr<RegisterNotificationResponseBuilder> builder(
     76       new RegisterNotificationResponseBuilder(interim,
     77                                               Event::PLAYBACK_STATUS_CHANGED));
     78 
     79   builder->data_ = play_status;
     80   return builder;
     81 }
     82 
     83 std::unique_ptr<RegisterNotificationResponseBuilder>
     84 RegisterNotificationResponseBuilder::MakeTrackChangedBuilder(
     85     bool interim, uint64_t track_uid) {
     86   std::unique_ptr<RegisterNotificationResponseBuilder> builder(
     87       new RegisterNotificationResponseBuilder(interim, Event::TRACK_CHANGED));
     88 
     89   builder->data_ = track_uid;
     90   return builder;
     91 }
     92 
     93 std::unique_ptr<RegisterNotificationResponseBuilder>
     94 RegisterNotificationResponseBuilder::MakePlaybackPositionBuilder(
     95     bool interim, uint32_t playback_pos) {
     96   std::unique_ptr<RegisterNotificationResponseBuilder> builder(
     97       new RegisterNotificationResponseBuilder(interim,
     98                                               Event::PLAYBACK_POS_CHANGED));
     99 
    100   builder->data_ = playback_pos;
    101   return builder;
    102 }
    103 
    104 std::unique_ptr<RegisterNotificationResponseBuilder>
    105 RegisterNotificationResponseBuilder::MakeNowPlayingBuilder(bool interim) {
    106   std::unique_ptr<RegisterNotificationResponseBuilder> builder(
    107       new RegisterNotificationResponseBuilder(
    108           interim, Event::NOW_PLAYING_CONTENT_CHANGED));
    109   return builder;
    110 }
    111 
    112 std::unique_ptr<RegisterNotificationResponseBuilder>
    113 RegisterNotificationResponseBuilder::MakeAvailablePlayersBuilder(bool interim) {
    114   std::unique_ptr<RegisterNotificationResponseBuilder> builder(
    115       new RegisterNotificationResponseBuilder(
    116           interim, Event::AVAILABLE_PLAYERS_CHANGED));
    117   return builder;
    118 }
    119 
    120 std::unique_ptr<RegisterNotificationResponseBuilder>
    121 RegisterNotificationResponseBuilder::MakeAddressedPlayerBuilder(
    122     bool interim, uint16_t player_id, uint16_t uid_counter) {
    123   std::unique_ptr<RegisterNotificationResponseBuilder> builder(
    124       new RegisterNotificationResponseBuilder(interim,
    125                                               Event::ADDRESSED_PLAYER_CHANGED));
    126   builder->data_ = ((uint32_t)player_id) << 16;
    127   builder->data_ |= uid_counter;
    128   return builder;
    129 }
    130 
    131 std::unique_ptr<RegisterNotificationResponseBuilder>
    132 RegisterNotificationResponseBuilder::MakeUidsChangedBuilder(
    133     bool interim, uint16_t uid_counter) {
    134   std::unique_ptr<RegisterNotificationResponseBuilder> builder(
    135       new RegisterNotificationResponseBuilder(interim, Event::UIDS_CHANGED));
    136 
    137   builder->data_ = uid_counter;
    138   return builder;
    139 }
    140 
    141 size_t RegisterNotificationResponseBuilder::size() const {
    142   size_t data_size = 0;
    143 
    144   // We specifically avoid having a default case here in order to ensure that
    145   // there is an error in case an event isn't handled.
    146   switch (event_) {
    147     case Event::PLAYBACK_STATUS_CHANGED:
    148       data_size = 1;
    149       break;
    150     case Event::TRACK_CHANGED:
    151       data_size = 8;
    152       break;
    153     case Event::PLAYBACK_POS_CHANGED:
    154       data_size = 4;
    155       break;
    156     case Event::PLAYER_APPLICATION_SETTING_CHANGED:
    157       LOG(FATAL) << "Player Application Notification Not Implemented";
    158       break;
    159     case Event::NOW_PLAYING_CONTENT_CHANGED:
    160       data_size = 0;
    161       break;
    162     case Event::AVAILABLE_PLAYERS_CHANGED:
    163       data_size = 0;
    164       break;
    165     case Event::ADDRESSED_PLAYER_CHANGED:
    166       data_size = 4;
    167       break;
    168     case Event::UIDS_CHANGED:
    169       data_size = 2;
    170       break;
    171     case Event::VOLUME_CHANGED:
    172       LOG(FATAL) << "Volume Changed Notification Not Implemented";
    173       break;
    174   }
    175 
    176   return VendorPacket::kMinSize() + 1 + data_size;
    177 }
    178 
    179 bool RegisterNotificationResponseBuilder::Serialize(
    180     const std::shared_ptr<::bluetooth::Packet>& pkt) {
    181   ReserveSpace(pkt, size());
    182 
    183   PacketBuilder::PushHeader(pkt);
    184 
    185   VendorPacketBuilder::PushHeader(pkt, size() - VendorPacket::kMinSize());
    186 
    187   AddPayloadOctets1(pkt, static_cast<uint8_t>(event_));
    188   switch (event_) {
    189     case Event::PLAYBACK_STATUS_CHANGED: {
    190       uint8_t playback_status = data_ & 0xFF;
    191       AddPayloadOctets1(pkt, playback_status);
    192       break;
    193     }
    194     case Event::TRACK_CHANGED: {
    195       AddPayloadOctets8(pkt, base::ByteSwap(data_));
    196       break;
    197     }
    198     case Event::PLAYBACK_POS_CHANGED: {
    199       uint32_t playback_pos = data_ & 0xFFFFFFFF;
    200       AddPayloadOctets4(pkt, base::ByteSwap(playback_pos));
    201       break;
    202     }
    203     case Event::PLAYER_APPLICATION_SETTING_CHANGED:
    204       break;  // No additional data
    205     case Event::NOW_PLAYING_CONTENT_CHANGED:
    206       break;  // No additional data
    207     case Event::AVAILABLE_PLAYERS_CHANGED:
    208       break;  // No additional data
    209     case Event::ADDRESSED_PLAYER_CHANGED: {
    210       uint16_t uid_counter = data_ & 0xFFFF;
    211       uint16_t player_id = (data_ >> 16) & 0xFFFF;
    212       AddPayloadOctets2(pkt, base::ByteSwap(player_id));
    213       AddPayloadOctets2(pkt, base::ByteSwap(uid_counter));
    214       break;
    215     }
    216     case Event::UIDS_CHANGED: {
    217       uint16_t uid_counter = data_ & 0xFFFF;
    218       AddPayloadOctets2(pkt, base::ByteSwap(uid_counter));
    219       break;
    220     }
    221     case Event::VOLUME_CHANGED:
    222       // TODO (apanicke): Add Volume Changed builder for when we are controller.
    223       LOG(FATAL) << "Volume Changed Notification Not Implemented";
    224       break;
    225   }
    226 
    227   return true;
    228 }
    229 
    230 Event RegisterNotificationRequest::GetEventRegistered() const {
    231   auto value = *(begin() + VendorPacket::kMinSize());
    232   return static_cast<Event>(value);
    233 }
    234 
    235 uint32_t RegisterNotificationRequest::GetInterval() const {
    236   auto it = begin() + VendorPacket::kMinSize() + static_cast<size_t>(1);
    237   return base::ByteSwap(it.extract<uint32_t>());
    238 }
    239 
    240 bool RegisterNotificationRequest::IsValid() const {
    241   return (size() == kMinSize());
    242 }
    243 
    244 std::string RegisterNotificationRequest::ToString() const {
    245   std::stringstream ss;
    246   ss << "RegisterNotificationPacket: " << std::endl;
    247   ss << "   cType = " << GetCType() << std::endl;
    248   ss << "   Subunit Type = " << loghex(GetSubunitType()) << std::endl;
    249   ss << "   Subunit ID = " << loghex(GetSubunitId()) << std::endl;
    250   ss << "   OpCode = " << GetOpcode() << std::endl;
    251   ss << "   Company ID = " << loghex(GetCompanyId()) << std::endl;
    252   ss << "   Command PDU = " << GetCommandPdu() << std::endl;
    253   ss << "   PacketType = " << GetPacketType() << std::endl;
    254   ss << "   Parameter Length = " << loghex(GetParameterLength()) << std::endl;
    255   ss << "   Event Registered = " << GetEventRegistered() << std::endl;
    256   ss << "   Interval = " << loghex(GetInterval()) << std::endl;
    257   ss << std::endl;
    258 
    259   return ss.str();
    260 }
    261 
    262 std::unique_ptr<RegisterNotificationRequestBuilder>
    263 RegisterNotificationRequestBuilder::MakeBuilder(Event event,
    264                                                 uint32_t interval) {
    265   std::unique_ptr<RegisterNotificationRequestBuilder> builder(
    266       new RegisterNotificationRequestBuilder(event, interval));
    267 
    268   return builder;
    269 }
    270 
    271 size_t RegisterNotificationRequestBuilder::size() const {
    272   return RegisterNotificationRequest::kMinSize();
    273 }
    274 
    275 bool RegisterNotificationRequestBuilder::Serialize(
    276     const std::shared_ptr<::bluetooth::Packet>& pkt) {
    277   ReserveSpace(pkt, size());
    278 
    279   PacketBuilder::PushHeader(pkt);
    280 
    281   VendorPacketBuilder::PushHeader(pkt, size() - VendorPacket::kMinSize());
    282 
    283   AddPayloadOctets1(pkt, static_cast<uint8_t>(event_));
    284 
    285   AddPayloadOctets4(pkt, base::ByteSwap(interval_));
    286 
    287   return true;
    288 }
    289 
    290 }  // namespace avrcp
    291 }  // namespace bluetooth