1 /******************************************************************************
2 *
3 * Copyright (C) 2006-2013 Broadcom Corporation
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18 #include <string.h>
19
20 #include "avrc_api.h"
21 #include "avrc_defs.h"
22 #include "avrc_int.h"
23 #include "bt_common.h"
24
25 /*****************************************************************************
26 * Global data
27 ****************************************************************************/
28
29 #if (AVRC_METADATA_INCLUDED == TRUE)
30 /*******************************************************************************
31 *
32 * Function avrc_bld_next_cmd
33 *
34 * Description This function builds the Request Continue or Abort command.
35 *
36 * Returns AVRC_STS_NO_ERROR, if the command is built successfully
37 * Otherwise, the error code.
38 *
39 ******************************************************************************/
avrc_bld_next_cmd(tAVRC_NEXT_CMD * p_cmd,BT_HDR * p_pkt)40 static tAVRC_STS avrc_bld_next_cmd(tAVRC_NEXT_CMD* p_cmd, BT_HDR* p_pkt) {
41 uint8_t *p_data, *p_start;
42
43 AVRC_TRACE_API("avrc_bld_next_cmd");
44
45 /* get the existing length, if any, and also the num attributes */
46 p_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset;
47 p_data = p_start + 2; /* pdu + rsvd */
48
49 /* add fixed lenth 1 - pdu_id (1) */
50 UINT16_TO_BE_STREAM(p_data, 1);
51 UINT8_TO_BE_STREAM(p_data, p_cmd->target_pdu);
52 p_pkt->len = (p_data - p_start);
53
54 return AVRC_STS_NO_ERROR;
55 }
56
57 /*****************************************************************************
58 * the following commands are introduced in AVRCP 1.4
59 ****************************************************************************/
60
61 #if (AVRC_ADV_CTRL_INCLUDED == TRUE)
62 /*******************************************************************************
63 *
64 * Function avrc_bld_set_abs_volume_cmd
65 *
66 * Description This function builds the Set Absolute Volume command.
67 *
68 * Returns AVRC_STS_NO_ERROR, if the command is built successfully
69 * Otherwise, the error code.
70 *
71 ******************************************************************************/
avrc_bld_set_abs_volume_cmd(tAVRC_SET_VOLUME_CMD * p_cmd,BT_HDR * p_pkt)72 static tAVRC_STS avrc_bld_set_abs_volume_cmd(tAVRC_SET_VOLUME_CMD* p_cmd,
73 BT_HDR* p_pkt) {
74 uint8_t *p_data, *p_start;
75
76 AVRC_TRACE_API("avrc_bld_set_abs_volume_cmd");
77 /* get the existing length, if any, and also the num attributes */
78 p_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset;
79 p_data = p_start + 2; /* pdu + rsvd */
80 /* add fixed lenth 1 - volume (1) */
81 UINT16_TO_BE_STREAM(p_data, 1);
82 UINT8_TO_BE_STREAM(p_data, (AVRC_MAX_VOLUME & p_cmd->volume));
83 p_pkt->len = (p_data - p_start);
84 return AVRC_STS_NO_ERROR;
85 }
86
87 /*******************************************************************************
88 *
89 * Function avrc_bld_register_notifn
90 *
91 * Description This function builds the register notification.
92 *
93 * Returns AVRC_STS_NO_ERROR, if the command is built successfully
94 * Otherwise, the error code.
95 *
96 ******************************************************************************/
avrc_bld_register_notifn(BT_HDR * p_pkt,uint8_t event_id,uint32_t event_param)97 static tAVRC_STS avrc_bld_register_notifn(BT_HDR* p_pkt, uint8_t event_id,
98 uint32_t event_param) {
99 uint8_t *p_data, *p_start;
100
101 AVRC_TRACE_API("avrc_bld_register_notifn");
102 /* get the existing length, if any, and also the num attributes */
103 // Set the notify value
104 p_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset;
105 p_data = p_start + 2; /* pdu + rsvd */
106 /* add fixed length 5 -*/
107 UINT16_TO_BE_STREAM(p_data, 5);
108 UINT8_TO_BE_STREAM(p_data, event_id);
109 UINT32_TO_BE_STREAM(p_data, event_param);
110 p_pkt->len = (p_data - p_start);
111 return AVRC_STS_NO_ERROR;
112 }
113 #endif
114
115 /*******************************************************************************
116 *
117 * Function avrc_bld_get_capability_cmd
118 *
119 * Description This function builds the get capability command.
120 *
121 * Returns AVRC_STS_NO_ERROR, if the command is built successfully
122 * Otherwise, the error code.
123 *
124 ******************************************************************************/
avrc_bld_get_capability_cmd(BT_HDR * p_pkt,uint8_t cap_id)125 static tAVRC_STS avrc_bld_get_capability_cmd(BT_HDR* p_pkt, uint8_t cap_id) {
126 AVRC_TRACE_API("avrc_bld_get_capability_cmd");
127 uint8_t* p_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset;
128 uint8_t* p_data = p_start + 2; /* pdu + rsvd */
129 /* add fixed length 1 -*/
130 UINT16_TO_BE_STREAM(p_data, 1);
131 UINT8_TO_BE_STREAM(p_data, cap_id);
132 p_pkt->len = (p_data - p_start);
133 return AVRC_STS_NO_ERROR;
134 }
135
136 /*******************************************************************************
137 *
138 * Function avrc_bld_list_player_app_attr_cmd
139 *
140 * Description This function builds the list player app attrib command.
141 *
142 * Returns AVRC_STS_NO_ERROR, if the command is built successfully
143 * Otherwise, the error code.
144 *
145 ******************************************************************************/
avrc_bld_list_player_app_attr_cmd(BT_HDR * p_pkt)146 static tAVRC_STS avrc_bld_list_player_app_attr_cmd(BT_HDR* p_pkt) {
147 AVRC_TRACE_API("avrc_bld_list_player_app_attr_cmd");
148 uint8_t* p_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset;
149 uint8_t* p_data = p_start + 2; /* pdu + rsvd */
150 /* add fixed length 1 -*/
151 UINT16_TO_BE_STREAM(p_data, 0);
152 p_pkt->len = (p_data - p_start);
153 return AVRC_STS_NO_ERROR;
154 }
155
156 /*******************************************************************************
157 *
158 * Function avrc_bld_list_player_app_values_cmd
159 *
160 * Description This function builds the list player app values command.
161 *
162 * Returns AVRC_STS_NO_ERROR, if the command is built successfully
163 * Otherwise, the error code.
164 *
165 ******************************************************************************/
avrc_bld_list_player_app_values_cmd(BT_HDR * p_pkt,uint8_t attrib_id)166 static tAVRC_STS avrc_bld_list_player_app_values_cmd(BT_HDR* p_pkt,
167 uint8_t attrib_id) {
168 AVRC_TRACE_API("avrc_bld_list_player_app_values_cmd");
169 uint8_t* p_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset;
170 uint8_t* p_data = p_start + 2; /* pdu + rsvd */
171 /* add fixed length 1 -*/
172 UINT16_TO_BE_STREAM(p_data, 1);
173 UINT8_TO_BE_STREAM(p_data, attrib_id);
174 p_pkt->len = (p_data - p_start);
175 return AVRC_STS_NO_ERROR;
176 }
177
178 /*******************************************************************************
179 *
180 * Function avrc_bld_get_current_player_app_values_cmd
181 *
182 * Description This function builds the get current player app setting
183 * values command.
184 *
185 * Returns AVRC_STS_NO_ERROR, if the command is built successfully
186 * Otherwise, the error code.
187 *
188 ******************************************************************************/
avrc_bld_get_current_player_app_values_cmd(BT_HDR * p_pkt,uint8_t num_attrib_id,uint8_t * attrib_ids)189 static tAVRC_STS avrc_bld_get_current_player_app_values_cmd(
190 BT_HDR* p_pkt, uint8_t num_attrib_id, uint8_t* attrib_ids) {
191 AVRC_TRACE_API("avrc_bld_get_current_player_app_values_cmd");
192 uint8_t* p_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset;
193 uint8_t* p_data = p_start + 2; /* pdu + rsvd */
194 uint8_t param_len =
195 num_attrib_id + 1; // 1 additional to hold num attributes feild
196 /* add length -*/
197 UINT16_TO_BE_STREAM(p_data, param_len);
198 UINT8_TO_BE_STREAM(p_data, num_attrib_id);
199 for (int count = 0; count < num_attrib_id; count++) {
200 UINT8_TO_BE_STREAM(p_data, attrib_ids[count]);
201 }
202 p_pkt->len = (p_data - p_start);
203 return AVRC_STS_NO_ERROR;
204 }
205
206 /*******************************************************************************
207 *
208 * Function avrc_bld_set_current_player_app_values_cmd
209 *
210 * Description This function builds the set current player app setting
211 * values command.
212 *
213 * Returns AVRC_STS_NO_ERROR, if the command is built successfully
214 * Otherwise, the error code.
215 *
216 ******************************************************************************/
avrc_bld_set_current_player_app_values_cmd(BT_HDR * p_pkt,uint8_t num_attrib_id,tAVRC_APP_SETTING * p_val)217 static tAVRC_STS avrc_bld_set_current_player_app_values_cmd(
218 BT_HDR* p_pkt, uint8_t num_attrib_id, tAVRC_APP_SETTING* p_val) {
219 AVRC_TRACE_API("avrc_bld_set_current_player_app_values_cmd");
220 uint8_t* p_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset;
221 uint8_t* p_data = p_start + 2; /* pdu + rsvd */
222 /* we have to store attrib- value pair
223 * 1 additional to store num elements
224 */
225 uint8_t param_len = (2 * num_attrib_id) + 1;
226 /* add length */
227 UINT16_TO_BE_STREAM(p_data, param_len);
228 UINT8_TO_BE_STREAM(p_data, num_attrib_id);
229 for (int count = 0; count < num_attrib_id; count++) {
230 UINT8_TO_BE_STREAM(p_data, p_val[count].attr_id);
231 UINT8_TO_BE_STREAM(p_data, p_val[count].attr_val);
232 }
233 p_pkt->len = (p_data - p_start);
234 return AVRC_STS_NO_ERROR;
235 }
236
237 /*******************************************************************************
238 *
239 * Function avrc_bld_get_player_app_setting_attr_text_cmd
240 *
241 * Description This function builds the get player app setting attribute
242 * text command.
243 *
244 * Returns AVRC_STS_NO_ERROR, if the command is built successfully
245 * Otherwise, the error code.
246 *
247 ******************************************************************************/
avrc_bld_get_player_app_setting_attr_text_cmd(BT_HDR * p_pkt,tAVRC_GET_APP_ATTR_TXT_CMD * p_cmd)248 static tAVRC_STS avrc_bld_get_player_app_setting_attr_text_cmd(
249 BT_HDR* p_pkt, tAVRC_GET_APP_ATTR_TXT_CMD* p_cmd) {
250 AVRC_TRACE_API("%s", __func__);
251
252 uint8_t* p_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset;
253 uint8_t* p_data = p_start + 2; /* pdu + rsvd */
254
255 uint8_t param_len = p_cmd->num_attr + 1;
256 /* add length */
257 UINT16_TO_BE_STREAM(p_data, param_len);
258 UINT8_TO_BE_STREAM(p_data, p_cmd->num_attr);
259 for (int count = 0; count < p_cmd->num_attr; count++) {
260 UINT8_TO_BE_STREAM(p_data, p_cmd->attrs[count]);
261 }
262 p_pkt->len = (p_data - p_start);
263 return AVRC_STS_NO_ERROR;
264 }
265
266 /*******************************************************************************
267 *
268 * Function avrc_bld_get_player_app_setting_value_text_cmd
269 *
270 * Description This function builds the get player app setting value
271 * text command.
272 *
273 * Returns AVRC_STS_NO_ERROR, if the command is built successfully
274 * Otherwise, the error code.
275 *
276 ******************************************************************************/
avrc_bld_get_player_app_setting_value_text_cmd(BT_HDR * p_pkt,tAVRC_GET_APP_VAL_TXT_CMD * p_cmd)277 static tAVRC_STS avrc_bld_get_player_app_setting_value_text_cmd(
278 BT_HDR* p_pkt, tAVRC_GET_APP_VAL_TXT_CMD* p_cmd) {
279 AVRC_TRACE_API("%s", __func__);
280
281 uint8_t* p_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset;
282 uint8_t* p_data = p_start + 2; /* pdu + rsvd */
283
284 uint8_t param_len = p_cmd->num_val + 1;
285 /* add length */
286 UINT16_TO_BE_STREAM(p_data, param_len);
287 UINT8_TO_BE_STREAM(p_data, p_cmd->num_val);
288 for (int count = 0; count < p_cmd->num_val; count++) {
289 UINT8_TO_BE_STREAM(p_data, p_cmd->vals[count]);
290 }
291 p_pkt->len = (p_data - p_start);
292 return AVRC_STS_NO_ERROR;
293 }
294
295 /*******************************************************************************
296 *
297 * Function avrc_bld_get_element_attr_cmd
298 *
299 * Description This function builds the get element attribute command.
300 *
301 * Returns AVRC_STS_NO_ERROR, if the command is built successfully
302 * Otherwise, the error code.
303 *
304 ******************************************************************************/
avrc_bld_get_element_attr_cmd(BT_HDR * p_pkt,uint8_t num_attrib,uint32_t * attrib_ids)305 static tAVRC_STS avrc_bld_get_element_attr_cmd(BT_HDR* p_pkt,
306 uint8_t num_attrib,
307 uint32_t* attrib_ids) {
308 AVRC_TRACE_API("avrc_bld_get_element_attr_cmd");
309 uint8_t* p_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset;
310 uint8_t* p_data = p_start + 2; /* pdu + rsvd */
311 /* we have to store attrib- value pair
312 * 1 additional to store num elements
313 */
314 uint8_t param_len = (4 * num_attrib) + 9;
315 /* add length */
316 UINT16_TO_BE_STREAM(p_data, param_len);
317 /* 8 bytes of identifier as 0 (playing)*/
318 UINT32_TO_BE_STREAM(p_data, 0);
319 UINT32_TO_BE_STREAM(p_data, 0);
320 UINT8_TO_BE_STREAM(p_data, num_attrib);
321 for (int count = 0; count < num_attrib; count++) {
322 UINT32_TO_BE_STREAM(p_data, attrib_ids[count]);
323 }
324 p_pkt->len = (p_data - p_start);
325 return AVRC_STS_NO_ERROR;
326 }
327
328 /*******************************************************************************
329 *
330 * Function avrc_bld_play_item_cmd
331 *
332 * Description This function builds the play item cmd
333 *
334 * Returns AVRC_STS_NO_ERROR, if the command is built successfully
335 * Otherwise, the error code.
336 *
337 ******************************************************************************/
avrc_bld_play_item_cmd(BT_HDR * p_pkt,uint8_t scope,uint8_t * uid,uint16_t uid_counter)338 static tAVRC_STS avrc_bld_play_item_cmd(BT_HDR* p_pkt, uint8_t scope,
339 uint8_t* uid, uint16_t uid_counter) {
340 AVRC_TRACE_API("avrc_bld_get_element_attr_cmd");
341 uint8_t* p_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset;
342 uint8_t* p_data = p_start + 2; /* pdu + rsvd */
343 /* add fixed length 11 */
344 UINT16_TO_BE_STREAM(p_data, 0xb);
345 /* Add scope */
346 UINT8_TO_BE_STREAM(p_data, scope);
347 /* Add UID */
348 ARRAY_TO_BE_STREAM(p_data, uid, AVRC_UID_SIZE);
349 /* Add UID Counter */
350 UINT16_TO_BE_STREAM(p_data, uid_counter);
351 p_pkt->len = (p_data - p_start);
352 return AVRC_STS_NO_ERROR;
353 }
354
355 /*******************************************************************************
356 *
357 * Function avrc_bld_get_play_status_cmd
358 *
359 * Description This function builds the get play status command.
360 *
361 * Returns AVRC_STS_NO_ERROR, if the command is built successfully
362 * Otherwise, the error code.
363 *
364 ******************************************************************************/
avrc_bld_get_play_status_cmd(BT_HDR * p_pkt)365 static tAVRC_STS avrc_bld_get_play_status_cmd(BT_HDR* p_pkt) {
366 AVRC_TRACE_API("avrc_bld_list_player_app_attr_cmd");
367 uint8_t* p_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset;
368 uint8_t* p_data = p_start + 2; /* pdu + rsvd */
369 /* add fixed length 0 -*/
370 UINT16_TO_BE_STREAM(p_data, 0);
371 p_pkt->len = (p_data - p_start);
372 return AVRC_STS_NO_ERROR;
373 }
374
375 /*******************************************************************************
376 *
377 * Function avrc_bld_get_folder_items_cmd
378 *
379 * Description This function builds the get folder items cmd.
380 *
381 * Returns AVRC_STS_NO_ERROR, if the command is built successfully
382 * Otherwise, the error code.
383 *
384 ******************************************************************************/
avrc_bld_get_folder_items_cmd(BT_HDR * p_pkt,const tAVRC_GET_ITEMS_CMD * cmd)385 static tAVRC_STS avrc_bld_get_folder_items_cmd(BT_HDR* p_pkt,
386 const tAVRC_GET_ITEMS_CMD* cmd) {
387 AVRC_TRACE_API(
388 "avrc_bld_get_folder_items_cmd scope %d, start_item %d, end_item %d",
389 cmd->scope, cmd->start_item, cmd->end_item);
390 uint8_t* p_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset;
391 /* This is where the PDU specific for AVRC starts
392 * AVRCP Spec 1.4 section 22.19 */
393 uint8_t* p_data = p_start + 1; /* pdu */
394
395 /* To get the list of all media players we simply need to use the predefined
396 * PDU mentioned in above spec. */
397 /* scope (1) + st item (4) + end item (4) + attr (1) */
398 UINT16_TO_BE_STREAM(p_data, 10);
399 UINT8_TO_BE_STREAM(p_data, cmd->scope); /* scope (1bytes) */
400 UINT32_TO_BE_STREAM(p_data, cmd->start_item); /* start item (4bytes) */
401 UINT32_TO_BE_STREAM(p_data, cmd->end_item); /* end item (4bytes) */
402 UINT8_TO_BE_STREAM(p_data, 0); /* attribute count = 0 (1bytes) */
403 p_pkt->len = (p_data - p_start);
404 return AVRC_STS_NO_ERROR;
405 }
406
407 /*******************************************************************************
408 *
409 * Function avrc_bld_change_folder_cmd
410 *
411 * Description This function builds the change folder command
412 *
413 * Returns AVRC_STS_NO_ERROR, if the command is built successfully
414 * Otherwise, the error code.
415 *
416 ******************************************************************************/
avrc_bld_change_folder_cmd(BT_HDR * p_pkt,const tAVRC_CHG_PATH_CMD * cmd)417 static tAVRC_STS avrc_bld_change_folder_cmd(BT_HDR* p_pkt,
418 const tAVRC_CHG_PATH_CMD* cmd) {
419 AVRC_TRACE_API("avrc_bld_change_folder_cmd");
420 uint8_t* p_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset;
421 /* This is where the PDU specific for AVRC starts
422 * AVRCP Spec 1.4 section 22.19 */
423 uint8_t* p_data = p_start + 1; /* pdu */
424
425 /* To change folder we need to provide the following:
426 * UID Counter (2) + Direction (1) + UID (8) = 11bytes
427 */
428 UINT16_TO_BE_STREAM(p_data, 11);
429 UINT16_TO_BE_STREAM(p_data, cmd->uid_counter);
430 UINT8_TO_BE_STREAM(p_data, cmd->direction);
431 ARRAY_TO_BE_STREAM(p_data, cmd->folder_uid, AVRC_UID_SIZE);
432 p_pkt->len = (p_data - p_start);
433 return AVRC_STS_NO_ERROR;
434 }
435
436 /*******************************************************************************
437 *
438 * Function avrc_bld_set_browsed_player_cmd
439 *
440 * Description This function builds the set browsed player cmd.
441 *
442 * Returns AVRC_STS_NO_ERROR, if the command is built successfully
443 * Otherwise, the error code.
444 *
445 ******************************************************************************/
avrc_bld_set_browsed_player_cmd(BT_HDR * p_pkt,const tAVRC_SET_BR_PLAYER_CMD * cmd)446 static tAVRC_STS avrc_bld_set_browsed_player_cmd(
447 BT_HDR* p_pkt, const tAVRC_SET_BR_PLAYER_CMD* cmd) {
448 AVRC_TRACE_API("%s", __func__);
449 uint8_t* p_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset;
450 /* This is where the PDU specific for AVRC starts
451 * AVRCP Spec 1.4 section 22.19 */
452 uint8_t* p_data = p_start + 1; /* pdu */
453
454 /* To change browsed player the following is the total length:
455 * Player ID (2)
456 */
457 UINT16_TO_BE_STREAM(p_data, 2); /* fixed length */
458 UINT16_TO_BE_STREAM(p_data, cmd->player_id);
459 p_pkt->len = (p_data - p_start);
460 return AVRC_STS_NO_ERROR;
461 }
462
463 /*******************************************************************************
464 *
465 * Function avrc_bld_set_addressed_player_cmd
466 *
467 * Description This function builds the set addressed player cmd.
468 *
469 * Returns AVRC_STS_NO_ERROR, if the command is built successfully
470 * Otherwise, the error code.
471 *
472 ******************************************************************************/
avrc_bld_set_addressed_player_cmd(BT_HDR * p_pkt,const tAVRC_SET_ADDR_PLAYER_CMD * cmd)473 static tAVRC_STS avrc_bld_set_addressed_player_cmd(
474 BT_HDR* p_pkt, const tAVRC_SET_ADDR_PLAYER_CMD* cmd) {
475 AVRC_TRACE_API("%s", __func__);
476 /* get the existing length, if any, and also the num attributes */
477 uint8_t* p_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset;
478 uint8_t* p_data = p_start + 2; /* pdu + rsvd */
479
480 /* To change addressed player the following is the total length:
481 * Player ID (2)
482 */
483 UINT16_TO_BE_STREAM(p_data, 2); /* fixed length */
484 UINT16_TO_BE_STREAM(p_data, cmd->player_id);
485 p_pkt->len = (p_data - p_start);
486 return AVRC_STS_NO_ERROR;
487 }
488
489 /*******************************************************************************
490 *
491 * Function avrc_bld_init_cmd_buffer
492 *
493 * Description This function initializes the command buffer based on PDU
494 *
495 * Returns NULL, if no GKI buffer or failure to build the message.
496 * Otherwise, the GKI buffer that contains the initialized
497 * message.
498 *
499 ******************************************************************************/
avrc_bld_init_cmd_buffer(tAVRC_COMMAND * p_cmd)500 static BT_HDR* avrc_bld_init_cmd_buffer(tAVRC_COMMAND* p_cmd) {
501 uint16_t chnl = AVCT_DATA_CTRL;
502 uint8_t opcode = avrc_opcode_from_pdu(p_cmd->pdu);
503 AVRC_TRACE_API("avrc_bld_init_cmd_buffer: pdu=%x, opcode=%x", p_cmd->pdu,
504 opcode);
505
506 uint16_t offset = 0;
507 switch (opcode) {
508 case AVRC_OP_BROWSE:
509 chnl = AVCT_DATA_BROWSE;
510 offset = AVCT_BROWSE_OFFSET;
511 break;
512
513 case AVRC_OP_PASS_THRU:
514 offset = AVRC_MSG_PASS_THRU_OFFSET;
515 break;
516
517 case AVRC_OP_VENDOR:
518 offset = AVRC_MSG_VENDOR_OFFSET;
519 break;
520 }
521
522 /* allocate and initialize the buffer */
523 BT_HDR* p_pkt = (BT_HDR*)osi_malloc(AVRC_META_CMD_BUF_SIZE);
524 uint8_t *p_data, *p_start;
525
526 p_pkt->layer_specific = chnl;
527 p_pkt->event = opcode;
528 p_pkt->offset = offset;
529 p_data = (uint8_t*)(p_pkt + 1) + p_pkt->offset;
530 p_start = p_data;
531
532 /* pass thru - group navigation - has a two byte op_id, so dont do it here */
533 if (opcode != AVRC_OP_PASS_THRU) *p_data++ = p_cmd->pdu;
534
535 switch (opcode) {
536 case AVRC_OP_VENDOR:
537 /* reserved 0, packet_type 0 */
538 UINT8_TO_BE_STREAM(p_data, 0);
539 /* continue to the next "case to add length */
540 /* add fixed lenth - 0 */
541 UINT16_TO_BE_STREAM(p_data, 0);
542 break;
543 }
544
545 p_pkt->len = (p_data - p_start);
546 p_cmd->cmd.opcode = opcode;
547
548 return p_pkt;
549 }
550
551 /*******************************************************************************
552 *
553 * Function AVRC_BldCommand
554 *
555 * Description This function builds the given AVRCP command to the given
556 * GKI buffer
557 *
558 * Returns AVRC_STS_NO_ERROR, if the command is built successfully
559 * Otherwise, the error code.
560 *
561 ******************************************************************************/
AVRC_BldCommand(tAVRC_COMMAND * p_cmd,BT_HDR ** pp_pkt)562 tAVRC_STS AVRC_BldCommand(tAVRC_COMMAND* p_cmd, BT_HDR** pp_pkt) {
563 tAVRC_STS status = AVRC_STS_BAD_PARAM;
564 bool alloc = false;
565 AVRC_TRACE_API("AVRC_BldCommand: pdu=%x status=%x", p_cmd->cmd.pdu,
566 p_cmd->cmd.status);
567 if (!p_cmd || !pp_pkt) {
568 AVRC_TRACE_API(
569 "AVRC_BldCommand. Invalid parameters passed. p_cmd=%p, pp_pkt=%p",
570 p_cmd, pp_pkt);
571 return AVRC_STS_BAD_PARAM;
572 }
573
574 if (*pp_pkt == NULL) {
575 *pp_pkt = avrc_bld_init_cmd_buffer(p_cmd);
576 if (*pp_pkt == NULL) {
577 AVRC_TRACE_API("AVRC_BldCommand: Failed to initialize command buffer");
578 return AVRC_STS_INTERNAL_ERR;
579 }
580 alloc = true;
581 }
582 status = AVRC_STS_NO_ERROR;
583 BT_HDR* p_pkt = *pp_pkt;
584
585 switch (p_cmd->pdu) {
586 case AVRC_PDU_REQUEST_CONTINUATION_RSP: /* 0x40 */
587 status = avrc_bld_next_cmd(&p_cmd->continu, p_pkt);
588 break;
589
590 case AVRC_PDU_ABORT_CONTINUATION_RSP: /* 0x41 */
591 status = avrc_bld_next_cmd(&p_cmd->abort, p_pkt);
592 break;
593 #if (AVRC_ADV_CTRL_INCLUDED == TRUE)
594 case AVRC_PDU_SET_ABSOLUTE_VOLUME: /* 0x50 */
595 status = avrc_bld_set_abs_volume_cmd(&p_cmd->volume, p_pkt);
596 break;
597 #endif
598 case AVRC_PDU_REGISTER_NOTIFICATION: /* 0x31 */
599 #if (AVRC_ADV_CTRL_INCLUDED == TRUE)
600 status = avrc_bld_register_notifn(p_pkt, p_cmd->reg_notif.event_id,
601 p_cmd->reg_notif.param);
602 #endif
603 break;
604 case AVRC_PDU_GET_CAPABILITIES:
605 status =
606 avrc_bld_get_capability_cmd(p_pkt, p_cmd->get_caps.capability_id);
607 break;
608 case AVRC_PDU_LIST_PLAYER_APP_ATTR:
609 status = avrc_bld_list_player_app_attr_cmd(p_pkt);
610 break;
611 case AVRC_PDU_LIST_PLAYER_APP_VALUES:
612 status = avrc_bld_list_player_app_values_cmd(
613 p_pkt, p_cmd->list_app_values.attr_id);
614 break;
615 case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE:
616 status = avrc_bld_get_current_player_app_values_cmd(
617 p_pkt, p_cmd->get_cur_app_val.num_attr, p_cmd->get_cur_app_val.attrs);
618 break;
619 case AVRC_PDU_SET_PLAYER_APP_VALUE:
620 status = avrc_bld_set_current_player_app_values_cmd(
621 p_pkt, p_cmd->set_app_val.num_val, p_cmd->set_app_val.p_vals);
622 break;
623 case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT:
624 avrc_bld_get_player_app_setting_attr_text_cmd(p_pkt,
625 &p_cmd->get_app_attr_txt);
626 break;
627 case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT:
628 avrc_bld_get_player_app_setting_value_text_cmd(p_pkt,
629 &p_cmd->get_app_val_txt);
630 break;
631 case AVRC_PDU_GET_ELEMENT_ATTR:
632 status = avrc_bld_get_element_attr_cmd(
633 p_pkt, p_cmd->get_elem_attrs.num_attr, p_cmd->get_elem_attrs.attrs);
634 break;
635 case AVRC_PDU_PLAY_ITEM:
636 status = avrc_bld_play_item_cmd(p_pkt, p_cmd->play_item.scope,
637 p_cmd->play_item.uid,
638 p_cmd->play_item.uid_counter);
639 break;
640 case AVRC_PDU_GET_PLAY_STATUS:
641 status = avrc_bld_get_play_status_cmd(p_pkt);
642 break;
643 case AVRC_PDU_GET_FOLDER_ITEMS:
644 status = avrc_bld_get_folder_items_cmd(p_pkt, &(p_cmd->get_items));
645 break;
646 case AVRC_PDU_CHANGE_PATH:
647 status = avrc_bld_change_folder_cmd(p_pkt, &(p_cmd->chg_path));
648 break;
649 case AVRC_PDU_SET_BROWSED_PLAYER:
650 status = avrc_bld_set_browsed_player_cmd(p_pkt, &(p_cmd->br_player));
651 break;
652 case AVRC_PDU_SET_ADDRESSED_PLAYER:
653 status = avrc_bld_set_addressed_player_cmd(p_pkt, &(p_cmd->addr_player));
654 break;
655 }
656
657 if (alloc && (status != AVRC_STS_NO_ERROR)) {
658 osi_free(p_pkt);
659 *pp_pkt = NULL;
660 }
661 AVRC_TRACE_API("AVRC_BldCommand: returning %d", status);
662 return status;
663 }
664 #endif /* (AVRC_METADATA_INCLUDED == TRUE) */
665