1 /*
2 * Copyright (C) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "avrcp_ct_notification.h"
17
18 namespace OHOS {
19 namespace bluetooth {
AvrcCtNotifyPacket(uint8_t eventId,uint32_t interval)20 AvrcCtNotifyPacket::AvrcCtNotifyPacket(uint8_t eventId, uint32_t interval)
21 : AvrcCtVendorPacket(),
22 interval_(AVRC_PLAYBACK_INTERVAL_1_SEC),
23 playStatus_(AVRC_PLAY_STATUS_ERROR),
24 volume_(AVRC_ABSOLUTE_VOLUME_INVALID)
25 {
26 HILOGI("enter");
27
28 crCode_ = AVRC_CT_CMD_CODE_NOTIFY;
29 pduId_ = AVRC_CT_PDU_ID_REGISTER_NOTIFICATION;
30 parameterLength_ = AVRC_CT_NOTIFY_PARAMETER_LENGTH;
31 eventId_ = eventId;
32 interval_ = interval;
33 }
34
AvrcCtNotifyPacket(Packet * pkt)35 AvrcCtNotifyPacket::AvrcCtNotifyPacket(Packet *pkt)
36 : AvrcCtVendorPacket(),
37 interval_(AVRC_PLAYBACK_INTERVAL_1_SEC),
38 playStatus_(AVRC_PLAY_STATUS_ERROR),
39 volume_(AVRC_ABSOLUTE_VOLUME_INVALID)
40 {
41 HILOGI("enter");
42
43 crCode_ = AVRC_CT_CMD_CODE_NOTIFY;
44 pduId_ = AVRC_CT_PDU_ID_REGISTER_NOTIFICATION;
45
46 DisassemblePacket(pkt);
47 }
48
~AvrcCtNotifyPacket()49 AvrcCtNotifyPacket::~AvrcCtNotifyPacket()
50 {
51 HILOGI("enter");
52
53 attributes_.clear();
54 values_.clear();
55 }
56
AssembleParameters(Packet * pkt)57 Packet *AvrcCtNotifyPacket::AssembleParameters(Packet *pkt)
58 {
59 HILOGI("enter");
60
61 size_t bufferSize = AVRC_CT_VENDOR_PARAMETER_LENGTH_SIZE + AVRC_CT_NOTIFY_PARAMETER_LENGTH;
62 HILOGI("BufferMalloc: %{public}zu", bufferSize);
63
64 auto buffer = BufferMalloc(bufferSize);
65 if (buffer == nullptr) {
66 HILOGE("BufferMalloc fail");
67 return pkt;
68 }
69 auto bufferPtr = static_cast<uint8_t *>(BufferPtr(buffer));
70
71 uint16_t offset = 0x0000;
72 offset += PushOctets2((bufferPtr + offset), parameterLength_);
73 HILOGI("parameterLength_: %{public}d", parameterLength_);
74
75 offset += PushOctets1((bufferPtr + offset), eventId_);
76 HILOGI("eventId_: %{public}x", eventId_);
77
78 PushOctets4((bufferPtr + offset), interval_);
79 HILOGI("interval_: %{public}d", interval_);
80
81 PacketPayloadAddLast(pkt, buffer);
82
83 BufferFree(buffer);
84
85 return pkt;
86 }
87
DisassembleParameters(uint8_t * buffer)88 bool AvrcCtNotifyPacket::DisassembleParameters(uint8_t *buffer)
89 {
90 HILOGI("enter");
91
92 isValid_ = false;
93
94 uint16_t offset = AVRC_CT_VENDOR_PARAMETER_LENGTH_OFFSET;
95 uint64_t payload = 0x00;
96 offset += PopOctets2((buffer + offset), payload);
97 parameterLength_ = static_cast<uint16_t>(payload);
98 HILOGI("parameterLength_: %{public}d", parameterLength_);
99
100 payload = 0x00;
101 PopOctets1((buffer + offset), payload);
102 eventId_ = static_cast<uint8_t>(payload);
103 HILOGI("eventId_: %{public}x", eventId_);
104
105 switch (eventId_) {
106 case AVRC_CT_EVENT_ID_PLAYBACK_STATUS_CHANGED:
107 isValid_ = DisassemblePlaybackStatus(buffer);
108 break;
109 case AVRC_CT_EVENT_ID_TRACK_CHANGED:
110 isValid_ = DisassembleTrackChanged(buffer);
111 break;
112 case AVRC_CT_EVENT_ID_PLAYBACK_POS_CHANGED:
113 isValid_ = DisassemblePlaybackPosChanged(buffer);
114 break;
115 case AVRC_CT_EVENT_ID_PLAYER_APPLICATION_SETTING_CHANGED:
116 isValid_ = DisassemblePlayerApplicationSettingChanged(buffer);
117 break;
118 case AVRC_CT_EVENT_ID_ADDRESSED_PLAYER_CHANGED:
119 isValid_ = DisassembleAddressedPlayerChanged(buffer);
120 break;
121 case AVRC_CT_EVENT_ID_UIDS_CHANGED:
122 isValid_ = DisassembleUidsChanged(buffer);
123 break;
124 case AVRC_CT_EVENT_ID_VOLUME_CHANGED:
125 isValid_ = DisassembleVolumeChanged(buffer);
126 break;
127 case AVRC_CT_EVENT_ID_TRACK_REACHED_END:
128 case AVRC_CT_EVENT_ID_TRACK_REACHED_START:
129 case AVRC_CT_EVENT_ID_NOW_PLAYING_CONTENT_CHANGED:
130 case AVRC_CT_EVENT_ID_AVAILABLE_PLAYERS_CHANGED:
131 /// FALL THROUGH
132 default:
133 /// Do nothing!
134 isValid_ = true;
135 break;
136 }
137
138 HILOGI("isValid_: %{public}d", isValid_);
139
140 return isValid_;
141 }
142
DisassemblePlaybackStatus(uint8_t * buffer)143 bool AvrcCtNotifyPacket::DisassemblePlaybackStatus(uint8_t *buffer)
144 {
145 HILOGI("enter");
146
147 isValid_ = false;
148
149 uint16_t offset = AVRC_CT_NOTIFY_EVENT_ID_OFFSET + AVRC_CT_NOTIFY_EVENT_ID_SIZE;
150 uint64_t payload = 0x00;
151 PopOctets1((buffer + offset), payload);
152 playStatus_ = static_cast<uint8_t>(payload);
153 HILOGI("playStatus_: %{public}x", playStatus_);
154
155 isValid_ = true;
156
157 return isValid_;
158 }
159
DisassembleTrackChanged(uint8_t * buffer)160 bool AvrcCtNotifyPacket::DisassembleTrackChanged(uint8_t *buffer)
161 {
162 HILOGI("enter");
163
164 isValid_ = false;
165
166 uint16_t offset = AVRC_CT_NOTIFY_EVENT_ID_OFFSET + AVRC_CT_NOTIFY_EVENT_ID_SIZE;
167 uint64_t payload = 0x00;
168 PopOctets8((buffer + offset), payload);
169 uid_ = payload;
170 HILOGI("uid_: %{public}jx", uid_);
171
172 isValid_ = true;
173
174 return isValid_;
175 }
176
DisassemblePlaybackPosChanged(uint8_t * buffer)177 bool AvrcCtNotifyPacket::DisassemblePlaybackPosChanged(uint8_t *buffer)
178 {
179 HILOGI("enter");
180
181 isValid_ = false;
182
183 uint16_t offset = AVRC_CT_NOTIFY_EVENT_ID_OFFSET + AVRC_CT_NOTIFY_EVENT_ID_SIZE;
184 uint64_t payload = 0x00;
185 PopOctets4((buffer + offset), payload);
186 playbackPos_ = static_cast<uint32_t>(payload);
187 HILOGI("playbackPos_: %{public}d", playbackPos_);
188
189 isValid_ = true;
190
191 return isValid_;
192 }
193
DisassemblePlayerApplicationSettingChanged(uint8_t * buffer)194 bool AvrcCtNotifyPacket::DisassemblePlayerApplicationSettingChanged(uint8_t *buffer)
195 {
196 HILOGI("enter");
197
198 isValid_ = false;
199
200 receivedFragments_++;
201 HILOGI("receivedFragments_: %{public}d", receivedFragments_);
202
203 uint16_t offset = AVRC_CT_NOTIFY_EVENT_ID_OFFSET + AVRC_CT_NOTIFY_EVENT_ID_SIZE;
204 uint64_t payload = 0x00;
205 offset += PopOctets1((buffer + offset), payload);
206 auto numOfAttributes = static_cast<uint8_t>(payload);
207 HILOGI("numOfAttributes: %{public}d", numOfAttributes);
208
209 for (int i = 0; i < numOfAttributes; i++) {
210 payload = 0x00;
211 offset += PopOctets1((buffer + offset), payload);
212 attributes_.push_back(static_cast<uint8_t>(payload));
213 HILOGI("attribute: %{public}x", attributes_.back());
214
215 offset += PopOctets1((buffer + offset), payload);
216 values_.push_back(static_cast<uint8_t>(payload));
217 HILOGI("value: %{public}x", values_.back());
218 }
219
220 return isValid_;
221 }
222
DisassembleAddressedPlayerChanged(uint8_t * buffer)223 bool AvrcCtNotifyPacket::DisassembleAddressedPlayerChanged(uint8_t *buffer)
224 {
225 HILOGI("enter");
226
227 isValid_ = false;
228
229 uint16_t offset = AVRC_CT_NOTIFY_EVENT_ID_OFFSET + AVRC_CT_NOTIFY_EVENT_ID_SIZE;
230 uint64_t payload = 0x00;
231 offset += PopOctets2((buffer + offset), payload);
232 playerId_ = static_cast<uint16_t>(payload);
233 HILOGI("playerId_: %{public}x", playerId_);
234
235 payload = 0x00;
236 PopOctets2((buffer + offset), payload);
237 uidCounter_ = static_cast<uint16_t>(payload);
238 HILOGI("uidCounter_: %{public}x", uidCounter_);
239
240 isValid_ = true;
241
242 return isValid_;
243 }
244
DisassembleUidsChanged(uint8_t * buffer)245 bool AvrcCtNotifyPacket::DisassembleUidsChanged(uint8_t *buffer)
246 {
247 HILOGI("enter");
248
249 isValid_ = false;
250
251 uint16_t offset = AVRC_CT_NOTIFY_EVENT_ID_OFFSET + AVRC_CT_NOTIFY_EVENT_ID_SIZE;
252 uint64_t payload = 0x00;
253 PopOctets2((buffer + offset), payload);
254 uidCounter_ = static_cast<uint16_t>(payload);
255 HILOGI("uidCounter_: %{public}x", uidCounter_);
256
257 isValid_ = true;
258
259 return isValid_;
260 }
261
DisassembleVolumeChanged(uint8_t * buffer)262 bool AvrcCtNotifyPacket::DisassembleVolumeChanged(uint8_t *buffer)
263 {
264 HILOGI("enter");
265
266 isValid_ = false;
267
268 uint16_t offset = AVRC_CT_NOTIFY_EVENT_ID_OFFSET + AVRC_CT_NOTIFY_EVENT_ID_SIZE;
269 uint64_t payload = 0x00;
270 PopOctets1((buffer + offset), payload);
271 volume_ = static_cast<uint8_t>(payload) & 0b01111111;
272 HILOGI("volume_: %{public}d", volume_);
273
274 isValid_ = true;
275
276 return isValid_;
277 }
278 } // namespace bluetooth
279 } // namespace OHOS