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