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_internal.h"
17
18 #include "avrcp_ct_browse.h"
19
20 namespace OHOS {
21 namespace bluetooth {
22 /******************************************************************
23 * AvrcCtBrowsePacket *
24 ******************************************************************/
25
AvrcCtBrowsePacket()26 AvrcCtBrowsePacket::AvrcCtBrowsePacket()
27 : pduId_(AVRC_CT_PDU_ID_INVALID),
28 parameterLength_(AVRC_CT_BROWSE_PARAMETER_LENGTH),
29 mtu_(AVRC_CT_DEFAULT_BROWSE_MTU_SIZE),
30 pkt_(nullptr),
31 isValid_(false)
32 {
33 HILOGI("enter");
34 }
35
~AvrcCtBrowsePacket()36 AvrcCtBrowsePacket::~AvrcCtBrowsePacket()
37 {
38 HILOGI("enter");
39
40 if (pkt_ != nullptr) {
41 PacketFree(pkt_);
42 pkt_ = nullptr;
43 }
44 }
45
AssemblePacket(void)46 const Packet *AvrcCtBrowsePacket::AssemblePacket(void)
47 {
48 HILOGI("enter");
49
50 return pkt_;
51 }
52
DisassemblePacket(Packet * pkt)53 bool AvrcCtBrowsePacket::DisassemblePacket(Packet *pkt)
54 {
55 HILOGI("enter");
56
57 return false;
58 }
59
60 /******************************************************************
61 * SetBrowsedPlayer *
62 ******************************************************************/
AvrcCtSbpPacket(uint16_t playerId)63 AvrcCtSbpPacket::AvrcCtSbpPacket(uint16_t playerId) : AvrcCtBrowsePacket(), status_(AVRC_ES_CODE_INVALID)
64 {
65 HILOGI("playerId: %{public}d", playerId);
66
67 pduId_ = AVRC_CT_PDU_ID_SET_BROWSED_PLAYER;
68 parameterLength_ = AVRC_CT_SBP_FIXED_CMD_PARAMETER_LENGTH;
69 playerId_ = playerId;
70 }
71
AvrcCtSbpPacket(Packet * pkt)72 AvrcCtSbpPacket::AvrcCtSbpPacket(Packet *pkt) : AvrcCtBrowsePacket(), status_(AVRC_ES_CODE_INVALID)
73 {
74 HILOGI("enter");
75
76 pduId_ = AVRC_CT_PDU_ID_SET_BROWSED_PLAYER;
77
78 DisassemblePacket(pkt);
79 }
80
~AvrcCtSbpPacket()81 AvrcCtSbpPacket::~AvrcCtSbpPacket()
82 {
83 HILOGI("enter");
84 }
85
AssemblePacket(void)86 const Packet *AvrcCtSbpPacket::AssemblePacket(void)
87 {
88 HILOGI("enter");
89
90 pkt_ = PacketMalloc(0x00, 0x00, AVRC_CT_SBP_FIXED_CMD_FRAME_SIZE);
91 auto buffer = static_cast<uint8_t *>(BufferPtr(PacketContinuousPayload(pkt_)));
92
93 uint16_t offset = 0x0000;
94 offset += PushOctets1((buffer + offset), pduId_);
95 HILOGI("pduId_: %{public}x", pduId_);
96
97 offset += PushOctets2((buffer + offset), parameterLength_);
98 HILOGI("parameterLength_: %{public}d", parameterLength_);
99
100 PushOctets2((buffer + offset), playerId_);
101 HILOGI("playerId_: %{public}x", playerId_);
102
103 return pkt_;
104 }
105
DisassemblePacket(Packet * pkt)106 bool AvrcCtSbpPacket::DisassemblePacket(Packet *pkt)
107 {
108 HILOGI("enter");
109
110 isValid_ = false;
111 size_t size = PacketPayloadSize(pkt);
112 if (size >= AVRC_CT_SBP_MIN_RSP_FRAME_SIZE) {
113 auto buffer = static_cast<uint8_t *>(BufferPtr(PacketContinuousPayload(pkt)));
114
115 uint16_t offset = 0x0000;
116 uint64_t payload = 0x00;
117 offset += PopOctets1((buffer + offset), payload);
118 pduId_ = static_cast<uint8_t>(payload);
119 HILOGI("pduId_: %{public}x", pduId_);
120
121 offset += PopOctets2((buffer + offset), payload);
122 parameterLength_ = static_cast<uint16_t>(payload);
123 HILOGI("parameterLength_: %{public}d", parameterLength_);
124
125 offset += PopOctets1((buffer + offset), payload);
126 status_ = static_cast<uint8_t>(payload);
127 HILOGI("status_: %{public}x", status_);
128
129 offset += PopOctets2((buffer + offset), payload);
130 uidCounter_ = static_cast<uint16_t>(payload);
131 HILOGI("uidCounter_: %{public}d", uidCounter_);
132
133 offset += PopOctets4((buffer + offset), payload);
134 numOfItems_ = static_cast<uint32_t>(payload);
135 HILOGI("numOfItems_: %{public}d", numOfItems_);
136
137 offset += PopOctets2((buffer + offset), payload);
138 auto characterSetId = static_cast<uint16_t>(payload);
139 HILOGI("characterSetId: %{public}x", characterSetId);
140 if (characterSetId != AVRC_MEDIA_CHARACTER_SET_UTF8) {
141 isValid_ = false;
142 HILOGE("The character set id is not UTF-8!");
143 }
144
145 offset += PopOctets1((buffer + offset), payload);
146 folderDepth_ = static_cast<uint8_t>(payload);
147 HILOGI("folderDepth_: %{public}d", folderDepth_);
148
149 DisassemblePacketName(buffer, offset);
150 } else {
151 HILOGI("The size of the packet is invalid!");
152 }
153
154 return isValid_;
155 }
156
DisassemblePacketName(uint8_t * buffer,uint16_t offset)157 void AvrcCtSbpPacket::DisassemblePacketName(uint8_t *buffer, uint16_t offset)
158 {
159 HILOGI("buffer: %{public}s, offset: %{public}d", buffer, offset);
160
161 uint64_t payload = 0x00;
162
163 isValid_ = false;
164
165 char *tempName = nullptr;
166 for (int i = 0; i < folderDepth_; i++) {
167 offset += PopOctets2((buffer + offset), payload);
168 uint16_t nameLength = static_cast<uint16_t>(payload);
169 HILOGI("[AVRCP TG] nameLength: %{public}d", nameLength);
170
171 tempName = new char[nameLength + 1];
172 for (int j = 0; j < nameLength; j++) {
173 offset += PopOctets1((buffer + offset), payload);
174 tempName[j] = static_cast<char>(payload);
175 }
176 tempName[nameLength] = '\0';
177 folderNames_.push_back(tempName);
178 AvrcpCtSafeDeleteArray(tempName, nameLength + 1);
179 HILOGI("folderName: %{public}s", folderNames_.back().c_str());
180 }
181
182 isValid_ = true;
183 }
184
185 /******************************************************************
186 * ChangePath *
187 ******************************************************************/
188
AvrcCtCpPacket(uint16_t uidCounter,uint8_t direction,uint64_t folderUid)189 AvrcCtCpPacket::AvrcCtCpPacket(uint16_t uidCounter, uint8_t direction, uint64_t folderUid)
190 : AvrcCtBrowsePacket(), direction_(direction), status_(AVRC_ES_CODE_INVALID)
191 {
192 HILOGI("uidCounter: %{public}d, direction: %{public}d, folderUid: %{public}llu",
193 uidCounter, direction, static_cast<unsigned long long>(folderUid));
194
195 pduId_ = AVRC_CT_PDU_ID_CHANGE_PATH;
196 parameterLength_ = AVRC_CT_CP_FIXED_CMD_PARAMETER_LENGTH;
197 uidCounter_ = uidCounter;
198 direction_ = direction;
199 folderUid_ = folderUid;
200 }
201
AvrcCtCpPacket(Packet * pkt)202 AvrcCtCpPacket::AvrcCtCpPacket(Packet *pkt)
203 : AvrcCtBrowsePacket(), direction_(AVRC_FOLDER_DIRECTION_INVALID), status_(AVRC_ES_CODE_INVALID)
204 {
205 HILOGI("enter");
206
207 pduId_ = AVRC_CT_PDU_ID_CHANGE_PATH;
208
209 DisassemblePacket(pkt);
210 }
211
~AvrcCtCpPacket()212 AvrcCtCpPacket::~AvrcCtCpPacket()
213 {
214 HILOGI("enter");
215 }
216
AssemblePacket(void)217 const Packet *AvrcCtCpPacket::AssemblePacket(void)
218 {
219 HILOGI("enter");
220
221 pkt_ = PacketMalloc(0x00, 0x00, AVRC_CT_CP_FIXED_CMD_FRAME_SIZE);
222 auto buffer = static_cast<uint8_t *>(BufferPtr(PacketContinuousPayload(pkt_)));
223
224 uint16_t offset = 0x0000;
225 offset += PushOctets1((buffer + offset), pduId_);
226 HILOGI("pduId_: %{public}x", pduId_);
227
228 offset += PushOctets2((buffer + offset), parameterLength_);
229 HILOGI("parameterLength_: %{public}d", parameterLength_);
230
231 offset += PushOctets2((buffer + offset), uidCounter_);
232 HILOGI("uidCounter_: %{public}d", uidCounter_);
233
234 offset += PushOctets1((buffer + offset), direction_);
235 HILOGI("direction_: %{public}x", direction_);
236
237 PushOctets8((buffer + offset), folderUid_);
238 HILOGI("folderUid_: %{public}jx", folderUid_);
239
240 return pkt_;
241 }
242
DisassemblePacket(Packet * pkt)243 bool AvrcCtCpPacket::DisassemblePacket(Packet *pkt)
244 {
245 HILOGI("enter");
246
247 isValid_ = false;
248 size_t size = PacketPayloadSize(pkt);
249 if (size >= AVRC_CT_CP_FIXED_RSP_FRAME_SIZE) {
250 auto buffer = static_cast<uint8_t *>(BufferPtr(PacketContinuousPayload(pkt)));
251
252 uint16_t offset = 0x0000;
253 uint64_t payload = 0x00;
254 offset += PopOctets1((buffer + offset), payload);
255 pduId_ = static_cast<uint8_t>(payload);
256 HILOGI("pduId_: %{public}x", pduId_);
257
258 offset += PopOctets2((buffer + offset), payload);
259 parameterLength_ = static_cast<uint16_t>(payload);
260 HILOGI("parameterLength_: %{public}d", parameterLength_);
261
262 offset += PopOctets1((buffer + offset), payload);
263 status_ = static_cast<uint8_t>(payload);
264 HILOGI("status_: %{public}x", status_);
265
266 PopOctets4((buffer + offset), payload);
267 numOfItems_ = static_cast<uint32_t>(payload);
268 HILOGI("numOfItems_: %{public}d", numOfItems_);
269
270 isValid_ = true;
271 } else {
272 HILOGI("The size of the packet is invalid!");
273 }
274
275 return isValid_;
276 }
277
278 /******************************************************************
279 * GetFolderItems *
280 ******************************************************************/
281
AvrcCtGfiPacket(uint8_t scope,uint32_t startItem,uint32_t endItem,const std::vector<uint32_t> & attributes)282 AvrcCtGfiPacket::AvrcCtGfiPacket(
283 uint8_t scope, uint32_t startItem, uint32_t endItem, const std::vector<uint32_t> &attributes)
284 : AvrcCtBrowsePacket(), scope_(scope), status_(AVRC_ES_CODE_INVALID)
285 {
286 HILOGI("scope: %{public}d, startItem: %{public}u, endItem: %{public}u", scope, startItem, endItem);
287
288 pduId_ = AVRC_CT_PDU_ID_GET_FOLDER_ITEMS;
289 scope_ = scope;
290 startItem_ = startItem;
291 endItem_ = endItem;
292 attributes_ = attributes;
293 }
294
AvrcCtGfiPacket(Packet * pkt)295 AvrcCtGfiPacket::AvrcCtGfiPacket(Packet *pkt) : AvrcCtBrowsePacket(),
296 scope_(AVRC_MEDIA_SCOPE_INVALID), status_(AVRC_ES_CODE_INVALID)
297 {
298 HILOGI("enter");
299
300 pduId_ = AVRC_CT_PDU_ID_GET_FOLDER_ITEMS;
301
302 DisassemblePacket(pkt);
303 }
304
~AvrcCtGfiPacket()305 AvrcCtGfiPacket::~AvrcCtGfiPacket()
306 {
307 HILOGI("enter");
308
309 attributes_.clear();
310 mpItems_.clear();
311 meItems_.clear();
312 }
313
AssemblePacket(void)314 const Packet *AvrcCtGfiPacket::AssemblePacket(void)
315 {
316 HILOGI("enter");
317
318 attributeCount_ = attributes_.size();
319
320 pkt_ = PacketMalloc(0x00,
321 0x00,
322 AVRC_CT_GFI_MIN_CMD_FRAME_SIZE + static_cast<size_t>(attributeCount_) * AVRC_CT_GFI_ATTRIBUTE_ID_SIZE);
323 auto buffer = static_cast<uint8_t *>(BufferPtr(PacketContinuousPayload(pkt_)));
324
325 uint16_t offset = 0x0000;
326 offset += PushOctets1((buffer + offset), pduId_);
327 HILOGI("pduId_: %{public}x", pduId_);
328
329 parameterLength_ = AVRC_CT_GFI_FIXED_CMD_PARAMETER_LENGTH + (attributeCount_ * AVRC_CT_GFI_ATTRIBUTE_ID_SIZE);
330 offset += PushOctets2((buffer + offset), parameterLength_);
331 HILOGI("parameterLength_: %{public}d", parameterLength_);
332
333 offset += PushOctets1((buffer + offset), scope_);
334 HILOGI("scope_: %{public}x", scope_);
335
336 offset += PushOctets4((buffer + offset), startItem_);
337 HILOGI("startItem_: %{public}d", startItem_);
338
339 offset += PushOctets4((buffer + offset), endItem_);
340 HILOGI("endItem_: %{public}d", endItem_);
341
342 if (attributes_.size() == 0) {
343 attributeCount_ = AVRC_ATTRIBUTE_COUNT_NO;
344 } else {
345 attributeCount_ = attributes_.size();
346 }
347 offset += PushOctets1((buffer + offset), attributeCount_);
348 HILOGI("attributeCount_: %{public}d", attributeCount_);
349
350 for (auto attribute : attributes_) {
351 offset += PushOctets4((buffer + offset), attribute);
352 HILOGI("attribute: %{public}x", attribute);
353 }
354
355 return pkt_;
356 }
357
DisassemblePacket(Packet * pkt)358 bool AvrcCtGfiPacket::DisassemblePacket(Packet *pkt)
359 {
360 HILOGI("enter");
361
362 isValid_ = false;
363 size_t size = PacketPayloadSize(pkt);
364 if (size >= AVRC_CT_GIA_MIN_RSP_FRAME_SIZE) {
365 auto buffer = static_cast<uint8_t *>(BufferPtr(PacketContinuousPayload(pkt)));
366
367 uint16_t offset = 0x0000;
368 uint64_t payload = 0x00;
369 offset += PopOctets1((buffer + offset), payload);
370 pduId_ = static_cast<uint8_t>(payload);
371 HILOGI("pduId_: %{public}x", pduId_);
372
373 offset += PopOctets2((buffer + offset), payload);
374 parameterLength_ = static_cast<uint16_t>(payload);
375 HILOGI("parameterLength_: %{public}d", parameterLength_);
376
377 offset += PopOctets1((buffer + offset), payload);
378 status_ = static_cast<uint8_t>(payload);
379 HILOGI("status_: %{public}x", status_);
380
381 offset += PopOctets2((buffer + offset), payload);
382 uidCounter_ = static_cast<uint16_t>(payload);
383 HILOGI("uidCounter_: %{public}d", uidCounter_);
384
385 offset += PopOctets2((buffer + offset), payload);
386 numOfItems_ = static_cast<uint16_t>(payload);
387 HILOGI("numOfItems_: %{public}d", numOfItems_);
388
389 uint8_t itemType = AVRC_MEDIA_TYPE_INVALID;
390 for (int i = 0; i < numOfItems_; i++) {
391 PopOctets1((buffer + offset), payload);
392 itemType = static_cast<uint8_t>(payload);
393 switch (itemType) {
394 case AVRC_MEDIA_TYPE_MEDIA_PLAYER_ITEM:
395 scope_ = AVRC_MEDIA_SCOPE_PLAYER_LIST;
396 offset += DisassembleMpParameter((buffer + offset));
397 break;
398 case AVRC_MEDIA_TYPE_FOLDER_ITEM:
399 /// FALL THROUGH
400 case AVRC_MEDIA_TYPE_MEDIA_ELEMENT_ITEM:
401 scope_ = AVRC_MEDIA_SCOPE_NOW_PLAYING;
402 offset += DisassembleMeParameter((buffer + offset));
403 break;
404 default:
405 HILOGI("The item type: %{public}x is invalid!", PopOctets1((buffer + offset), payload));
406 break;
407 }
408 }
409 } else {
410 HILOGI("The size of the packet is invalid!");
411 }
412
413 return isValid_;
414 }
415
DisassembleMpParameter(uint8_t * buffer)416 uint16_t AvrcCtGfiPacket::DisassembleMpParameter(uint8_t *buffer)
417 {
418 HILOGI("buffer: %{public}s", buffer);
419
420 isValid_ = true;
421
422 uint16_t offset = 0x00;
423 uint64_t payload = 0x00;
424 offset += PopOctets1((buffer + offset), payload);
425 auto itemType = static_cast<uint8_t>(payload);
426 HILOGI("itemType: %{public}x", itemType);
427
428 offset += PopOctets2((buffer + offset), payload);
429 auto itemLength = static_cast<uint16_t>(payload);
430 HILOGI("itemLength: %{public}d", itemLength);
431
432 offset += PopOctets2((buffer + offset), payload);
433 auto playerId = static_cast<uint16_t>(payload);
434 HILOGI("playerId: %{public}x", playerId);
435
436 offset += PopOctets1((buffer + offset), payload);
437 auto majorType = static_cast<uint8_t>(payload);
438 HILOGI("majorType: %{public}x", majorType);
439
440 offset += PopOctets4((buffer + offset), payload);
441 auto subType = static_cast<uint32_t>(payload);
442 HILOGI("subType: %{public}x", subType);
443
444 offset += PopOctets1((buffer + offset), payload);
445 auto playStatus = static_cast<uint8_t>(payload);
446 HILOGI("playStatus: %{public}x", playStatus);
447
448 std::vector<uint8_t> features;
449 for (int i = 0; i < AVRC_CT_GFI_VALID_FEATURE_OCTETS; i++) {
450 offset += PopOctets1((buffer + offset), payload);
451 features.push_back(static_cast<uint8_t>(payload));
452 HILOGI("feature: %{public}x", features.back());
453 }
454
455 offset += PopOctets2((buffer + offset), payload);
456 auto characterSetId = static_cast<uint16_t>(payload);
457 HILOGI("characterSetId: %{public}x", characterSetId);
458 if (characterSetId != AVRC_MEDIA_CHARACTER_SET_UTF8) {
459 isValid_ = false;
460 HILOGI("The character set id is not UTF-8!");
461 }
462
463 std::string name;
464 offset = DisassembleMpParameterName(buffer, offset, name);
465
466 AvrcMpItem mpItem(itemType, playerId, majorType, subType, playStatus, features, name);
467 mpItems_.push_back(mpItem);
468
469 return offset;
470 }
471
DisassembleMpParameterName(uint8_t * buffer,uint16_t offset,std::string & name)472 uint16_t AvrcCtGfiPacket::DisassembleMpParameterName(uint8_t *buffer, uint16_t offset, std::string &name)
473 {
474 HILOGI("buffer: %{public}s, offset: %{public}d", buffer, offset);
475
476 isValid_ = false;
477
478 uint64_t payload = 0x00;
479
480 offset += PopOctets2((buffer + offset), payload);
481 auto nameLength = static_cast<uint16_t>(payload);
482 HILOGI("nameLength: %{public}d", nameLength);
483
484 char *tempName = nullptr;
485 tempName = new char[nameLength + 1];
486 for (int j = 0; j < nameLength; j++) {
487 offset += PopOctets1((buffer + offset), payload);
488 tempName[j] = static_cast<char>(payload);
489 }
490 tempName[nameLength] = '\0';
491 name = std::string(tempName);
492 AvrcpCtSafeDeleteArray(tempName, nameLength + 1);
493 HILOGI("name: %{public}s", name.c_str());
494
495 isValid_ = true;
496
497 return offset;
498 }
499
DisassembleMeParameter(uint8_t * buffer)500 uint16_t AvrcCtGfiPacket::DisassembleMeParameter(uint8_t *buffer)
501 {
502 HILOGI("buffer: %{public}s", buffer);
503
504 isValid_ = true;
505
506 uint16_t offset = 0x00;
507 uint64_t payload = 0x00;
508 offset += PopOctets1((buffer + offset), payload);
509 auto itemType = static_cast<uint8_t>(payload);
510 HILOGI("itemType: %{public}x", itemType);
511
512 offset += PopOctets2((buffer + offset), payload);
513 auto itemLength = static_cast<uint16_t>(payload);
514 HILOGI("itemLength: %{public}d", itemLength);
515
516 offset += PopOctets8((buffer + offset), payload);
517 auto uid = static_cast<uint64_t>(payload);
518 HILOGI("uid: %{public}jx", uid);
519
520 offset += PopOctets1((buffer + offset), payload);
521 auto type = static_cast<uint8_t>(payload);
522 HILOGI("type: %{public}x", type);
523
524 uint8_t playable = AVRC_MEDIA_FOLDER_PLAYABLE_RESERVED;
525 if (itemType == AVRC_MEDIA_TYPE_FOLDER_ITEM) {
526 offset += PopOctets1((buffer + offset), payload);
527 playable = static_cast<uint8_t>(payload);
528 }
529 HILOGI("playable: %{public}x", playable);
530
531 offset += PopOctets2((buffer + offset), payload);
532 auto characterSetId = static_cast<uint16_t>(payload);
533 HILOGI("characterSetId: %{public}x", characterSetId);
534 if (characterSetId != AVRC_MEDIA_CHARACTER_SET_UTF8) {
535 isValid_ = false;
536 HILOGE("The character set id is not UTF-8!");
537 }
538
539 std::string name;
540 offset = DisassembleMeParameterName(buffer, offset, name);
541
542 std::vector<uint32_t> attributes;
543 std::vector<std::string> values;
544 offset = DisassembleMeParameterAttributesAndValues(buffer, offset, itemType, attributes, values);
545
546 AvrcMeItem meItem(itemType, uid, type, playable, name, attributes, values);
547 meItems_.push_back(meItem);
548
549 return offset;
550 }
551
DisassembleMeParameterName(uint8_t * buffer,uint16_t offset,std::string & name)552 uint16_t AvrcCtGfiPacket::DisassembleMeParameterName(uint8_t *buffer, uint16_t offset, std::string &name)
553 {
554 HILOGI("buffer: %{public}s, offset: %{public}d", buffer, offset);
555
556 isValid_ = false;
557
558 uint64_t payload = 0x00;
559
560 offset += PopOctets2((buffer + offset), payload);
561 auto nameLength = static_cast<uint16_t>(payload);
562 HILOGI("nameLength: %{public}d", nameLength);
563
564 char *tempName = nullptr;
565 tempName = new char[nameLength + 1];
566 for (int j = 0; j < nameLength; j++) {
567 payload = 0x00;
568 offset += PopOctets1((buffer + offset), payload);
569 tempName[j] = static_cast<char>(payload);
570 }
571 tempName[nameLength] = '\0';
572 name = std::string(tempName);
573 AvrcpCtSafeDeleteArray(tempName, nameLength + 1);
574 HILOGI("name: %{public}s", name.c_str());
575
576 isValid_ = true;
577
578 return offset;
579 }
580
DisassembleMeParameterAttributesAndValues(uint8_t * buffer,uint16_t offset,uint8_t itemType,std::vector<uint32_t> & attributes,std::vector<std::string> & values)581 uint16_t AvrcCtGfiPacket::DisassembleMeParameterAttributesAndValues(uint8_t *buffer, uint16_t offset, uint8_t itemType,
582 std::vector<uint32_t> &attributes, std::vector<std::string> &values)
583 {
584 HILOGI("buffer: %{public}s, offset: %{public}d, itemType: %{public}d", buffer, offset, itemType);
585
586 isValid_ = false;
587
588 if (itemType == AVRC_MEDIA_TYPE_MEDIA_ELEMENT_ITEM) {
589 uint64_t payload = 0x00;
590 offset += PopOctets1((buffer + offset), payload);
591 auto numOfAttributes = static_cast<uint8_t>(payload);
592 HILOGI("numOfAttributes: %{public}d", numOfAttributes);
593
594 for (int i = 0; i < numOfAttributes; i++) {
595 offset += PopOctets4((buffer + offset), payload);
596 attributes.push_back(static_cast<uint32_t>(payload));
597 HILOGI("attribute: %{public}x", attributes.back());
598
599 offset += PopOctets2((buffer + offset), payload);
600 auto characterSetId = static_cast<uint16_t>(payload);
601 HILOGI("characterSetId: %{public}x", characterSetId);
602 if (characterSetId != AVRC_MEDIA_CHARACTER_SET_UTF8) {
603 isValid_ = false;
604 HILOGE("The character set id is not UTF-8!");
605 }
606
607 offset += PopOctets2((buffer + offset), payload);
608 auto valueLength = static_cast<uint16_t>(payload);
609 HILOGI("valueLength: %{public}d", valueLength);
610
611 char *tempName = nullptr;
612 tempName = new char[valueLength + 1];
613 for (int j = 0; j < valueLength; j++) {
614 offset += PopOctets1((buffer + offset), payload);
615 tempName[j] = static_cast<char>(payload);
616 }
617 tempName[valueLength] = '\0';
618 values.push_back(tempName);
619 AvrcpCtSafeDeleteArray(tempName, valueLength + 1);
620 HILOGI("value: %{public}s", values.back().c_str());
621 }
622 }
623
624 isValid_ = true;
625
626 return offset;
627 }
628
629 /******************************************************************
630 * GetItemAttributes *
631 ******************************************************************/
632
AvrcCtGiaPacket(uint8_t scope,uint64_t uid,uint16_t uidCounter,const std::vector<uint32_t> & attributes)633 AvrcCtGiaPacket::AvrcCtGiaPacket(
634 uint8_t scope, uint64_t uid, uint16_t uidCounter, const std::vector<uint32_t> &attributes)
635 : AvrcCtBrowsePacket(), scope_(scope), status_(AVRC_ES_CODE_INVALID)
636 {
637 HILOGI("scope: %{public}d, uid: %{public}llu, uidCounter: %{public}d",
638 scope, static_cast<unsigned long long>(uid), uidCounter);
639
640 pduId_ = AVRC_CT_PDU_ID_GET_ITEM_ATTRIBUTES;
641 scope_ = scope;
642 uid_ = uid;
643 uidCounter_ = uidCounter;
644 attributes_ = attributes;
645 }
646
AvrcCtGiaPacket(Packet * pkt)647 AvrcCtGiaPacket::AvrcCtGiaPacket(Packet *pkt) : AvrcCtBrowsePacket(), scope_(AVRC_MEDIA_SCOPE_INVALID), status_(AVRC_ES_CODE_INVALID)
648 {
649 HILOGI("enter");
650
651 pduId_ = AVRC_CT_PDU_ID_GET_ITEM_ATTRIBUTES;
652
653 DisassemblePacket(pkt);
654 }
655
~AvrcCtGiaPacket()656 AvrcCtGiaPacket::~AvrcCtGiaPacket()
657 {
658 HILOGI("enter");
659
660 attributes_.clear();
661 values_.clear();
662 }
663
AssemblePacket(void)664 const Packet *AvrcCtGiaPacket::AssemblePacket(void)
665 {
666 HILOGI("enter");
667
668 numOfAttributes_ = attributes_.size();
669
670 pkt_ = PacketMalloc(0x00,
671 0x00,
672 AVRC_CT_GIA_MIN_CMD_FRAME_SIZE + static_cast<size_t>(numOfAttributes_) * AVRC_CT_GIA_ATTRIBUTE_ID_SIZE);
673 auto buffer = static_cast<uint8_t *>(BufferPtr(PacketContinuousPayload(pkt_)));
674
675 uint16_t offset = 0x0000;
676 offset += PushOctets1((buffer + offset), pduId_);
677 HILOGI("pduId_: %{public}x", pduId_);
678
679 parameterLength_ = AVRC_CT_GIA_FIXED_CMD_PARAMETER_LENGTH + (numOfAttributes_ * AVRC_CT_GIA_ATTRIBUTE_ID_SIZE);
680 offset += PushOctets2((buffer + offset), parameterLength_);
681 HILOGI("parameterLength_: %{public}d", parameterLength_);
682
683 offset += PushOctets1((buffer + offset), scope_);
684 HILOGI("scope_: %{public}x", scope_);
685
686 offset += PushOctets8((buffer + offset), uid_);
687 HILOGI("uid_: %{public}jx", uid_);
688
689 offset += PushOctets2((buffer + offset), uidCounter_);
690 HILOGI("uidCounter_: %{public}d", uidCounter_);
691
692 offset += PushOctets1((buffer + offset), numOfAttributes_);
693 HILOGI("numOfAttributes_: %{public}d", numOfAttributes_);
694
695 for (auto attribute : attributes_) {
696 offset += PushOctets4((buffer + offset), attribute);
697 HILOGI("attribute: %{public}x", attribute);
698 }
699
700 return pkt_;
701 }
702
DisassemblePacket(Packet * pkt)703 bool AvrcCtGiaPacket::DisassemblePacket(Packet *pkt)
704 {
705 HILOGI("enter");
706
707 isValid_ = false;
708 size_t size = PacketPayloadSize(pkt);
709 if (size >= AVRC_CT_GIA_MIN_RSP_FRAME_SIZE) {
710 auto buffer = static_cast<uint8_t *>(BufferPtr(PacketContinuousPayload(pkt)));
711
712 uint16_t offset = 0x0000;
713 uint64_t payload = 0x00;
714 offset += PopOctets1((buffer + offset), payload);
715 pduId_ = static_cast<uint8_t>(payload);
716 HILOGI("pduId_: %{public}x", pduId_);
717
718 offset += PopOctets2((buffer + offset), payload);
719 parameterLength_ = static_cast<uint16_t>(payload);
720 HILOGI("parameterLength_: %{public}d", parameterLength_);
721
722 offset += PopOctets1((buffer + offset), payload);
723 status_ = static_cast<uint8_t>(payload);
724 HILOGI("status_: %{public}x", status_);
725
726 offset += PopOctets1((buffer + offset), payload);
727 numOfAttributes_ = static_cast<uint8_t>(payload);
728 HILOGI("numOfAttributes_: %{public}d", numOfAttributes_);
729
730 uint16_t characterSetId = AVRC_MEDIA_CHARACTER_SET_UTF8;
731 for (int i = 0; i < numOfAttributes_; i++) {
732 offset += PopOctets4((buffer + offset), payload);
733 attributes_.push_back(static_cast<uint32_t>(payload));
734 HILOGI("attribute: %{public}x", attributes_.back());
735
736 offset += PopOctets2((buffer + offset), payload);
737 characterSetId = static_cast<uint16_t>(payload);
738 HILOGI("characterSetId: %{public}x", characterSetId);
739 if (characterSetId != AVRC_MEDIA_CHARACTER_SET_UTF8) {
740 isValid_ = false;
741 HILOGE("The character set id is not UTF-8!");
742 }
743
744 DisassemblePacketName(buffer, offset);
745 }
746 } else {
747 HILOGI("The packet is invalid!");
748 }
749
750 return isValid_;
751 }
752
DisassemblePacketName(uint8_t * buffer,uint16_t & offset)753 void AvrcCtGiaPacket::DisassemblePacketName(uint8_t *buffer, uint16_t &offset)
754 {
755 HILOGI("buffer: %{public}s, offset: %{public}d", buffer, offset);
756
757 isValid_ = false;
758
759 uint64_t payload = 0x00;
760
761 offset += PopOctets2((buffer + offset), payload);
762 auto valueLength = static_cast<uint16_t>(payload);
763 HILOGI("valueLength: %{public}d", valueLength);
764
765 char *tempName = nullptr;
766 tempName = new char[valueLength + 1];
767 for (int j = 0; j < valueLength; j++) {
768 payload = 0x00;
769 offset += PopOctets1((buffer + offset), payload);
770 tempName[j] = static_cast<char>(payload);
771 }
772 tempName[valueLength] = '\0';
773 values_.push_back(tempName);
774 AvrcpCtSafeDeleteArray(tempName, valueLength + 1);
775 HILOGI("value: %{public}s", values_.back().c_str());
776
777 isValid_ = true;
778 }
779
780 /******************************************************************
781 * GetTotalNumberOfItems *
782 ******************************************************************/
783
AvrcCtGtnoiPacket(uint8_t scope)784 AvrcCtGtnoiPacket::AvrcCtGtnoiPacket(uint8_t scope) : AvrcCtBrowsePacket(), scope_(scope), status_(AVRC_ES_CODE_INVALID)
785 {
786 HILOGI("scope: %{public}d", scope);
787
788 pduId_ = AVRC_CT_PDU_ID_GET_TOTAL_NUMBER_OF_ITEMS;
789 parameterLength_ = AVRC_CT_GTNOI_FIXED_CMD_PARAMETER_LENGTH;
790 scope_ = scope;
791 }
792
AvrcCtGtnoiPacket(Packet * pkt)793 AvrcCtGtnoiPacket::AvrcCtGtnoiPacket(Packet *pkt)
794 : AvrcCtBrowsePacket(), scope_(AVRC_MEDIA_SCOPE_INVALID), status_(AVRC_ES_CODE_INVALID)
795 {
796 HILOGI("enter");
797
798 pduId_ = AVRC_CT_PDU_ID_GET_TOTAL_NUMBER_OF_ITEMS;
799
800 DisassemblePacket(pkt);
801 }
802
~AvrcCtGtnoiPacket()803 AvrcCtGtnoiPacket::~AvrcCtGtnoiPacket()
804 {
805 HILOGI("enter");
806 }
807
AssemblePacket(void)808 const Packet *AvrcCtGtnoiPacket::AssemblePacket(void)
809 {
810 HILOGI("enter");
811
812 pkt_ = PacketMalloc(0x00, 0x00, AVRC_CT_GTNOI_FIXED_CMD_FRAME_SIZE);
813 auto buffer = static_cast<uint8_t *>(BufferPtr(PacketContinuousPayload(pkt_)));
814
815 uint16_t offset = 0x0000;
816 offset += PushOctets1((buffer + offset), pduId_);
817 HILOGI("pduId_: %{public}x", pduId_);
818
819 offset += PushOctets2((buffer + offset), parameterLength_);
820 HILOGI("parameterLength_: %{public}d", parameterLength_);
821
822 PushOctets1((buffer + offset), scope_);
823 HILOGI("scope_: %{public}x", scope_);
824
825 return pkt_;
826 }
827
DisassemblePacket(Packet * pkt)828 bool AvrcCtGtnoiPacket::DisassemblePacket(Packet *pkt)
829 {
830 HILOGI("enter");
831
832 isValid_ = false;
833 size_t size = PacketPayloadSize(pkt);
834 if (size >= AVRC_CT_GTNOI_FIXED_RSP_FRAME_SIZE) {
835 auto buffer = static_cast<uint8_t *>(BufferPtr(PacketContinuousPayload(pkt)));
836
837 uint16_t offset = 0x0000;
838 uint64_t payload = 0x00;
839 offset += PopOctets1((buffer + offset), payload);
840 pduId_ = static_cast<uint8_t>(payload);
841 HILOGI("pduId_: %{public}x", pduId_);
842
843 offset += PopOctets2((buffer + offset), payload);
844 parameterLength_ = static_cast<uint16_t>(payload);
845 HILOGI("parameterLength_: %{public}d", parameterLength_);
846
847 offset += PopOctets1((buffer + offset), payload);
848 status_ = static_cast<uint8_t>(payload);
849 HILOGI("status_: %{public}x", status_);
850
851 offset += PopOctets2((buffer + offset), payload);
852 uidCounter_ = static_cast<uint16_t>(payload);
853 HILOGI("uidCounter_: %{public}d", uidCounter_);
854
855 PopOctets4((buffer + offset), payload);
856 numOfItems_ = static_cast<uint32_t>(payload);
857 HILOGI("numOfItems_: %{public}d", numOfItems_);
858
859 isValid_ = true;
860 } else {
861 HILOGI("The size of the packet is invalid!");
862 }
863
864 return isValid_;
865 }
866 } // namespace bluetooth
867 } // namespace OHOS