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