• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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