1/******************************************************************************
2 *
3 *  Copyright (C) 2003-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 "gki.h"
21#include "avrc_api.h"
22#include "avrc_defs.h"
23#include "avrc_int.h"
24
25/*****************************************************************************
26**  Global data
27*****************************************************************************/
28#if (AVRC_METADATA_INCLUDED == TRUE)
29
30/*******************************************************************************
31**
32** Function         avrc_bld_get_capability_rsp
33**
34** Description      This function builds the Get Capability response.
35**
36** Returns          AVRC_STS_NO_ERROR, if the response is built successfully
37**                  Otherwise, the error code.
38**
39*******************************************************************************/
40static tAVRC_STS avrc_bld_get_capability_rsp (tAVRC_GET_CAPS_RSP *p_rsp, BT_HDR *p_pkt)
41{
42    UINT8   *p_data, *p_start, *p_len, *p_count;
43    UINT16  len = 0;
44    UINT8   xx;
45    UINT32  *p_company_id;
46    UINT8   *p_event_id;
47    tAVRC_STS status = AVRC_STS_NO_ERROR;
48
49    if (!(AVRC_IS_VALID_CAP_ID(p_rsp->capability_id)))
50    {
51        AVRC_TRACE_ERROR1("avrc_bld_get_capability_rsp bad parameter. p_rsp: %x", p_rsp);
52        status = AVRC_STS_BAD_PARAM;
53        return status;
54    }
55
56    AVRC_TRACE_API0("avrc_bld_get_capability_rsp");
57    /* get the existing length, if any, and also the num attributes */
58    p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
59    p_data = p_len = p_start + 2; /* pdu + rsvd */
60
61    BE_STREAM_TO_UINT16(len, p_data);
62    UINT8_TO_BE_STREAM(p_data, p_rsp->capability_id);
63    p_count = p_data;
64
65    if (len == 0)
66    {
67        *p_count = p_rsp->count;
68        p_data++;
69        len = 2; /* move past the capability_id and count */
70    }
71    else
72    {
73        p_data = p_start + p_pkt->len;
74        *p_count += p_rsp->count;
75    }
76
77    if (p_rsp->capability_id == AVRC_CAP_COMPANY_ID)
78    {
79        p_company_id = p_rsp->param.company_id;
80        for (xx=0; xx< p_rsp->count; xx++)
81        {
82            UINT24_TO_BE_STREAM(p_data, p_company_id[xx]);
83        }
84        len += p_rsp->count * 3;
85    }
86    else
87    {
88        p_event_id = p_rsp->param.event_id;
89        *p_count = 0;
90        for (xx=0; xx< p_rsp->count; xx++)
91        {
92            if (AVRC_IS_VALID_EVENT_ID(p_event_id[xx]))
93            {
94                (*p_count)++;
95                UINT8_TO_BE_STREAM(p_data, p_event_id[xx]);
96            }
97        }
98        len += (*p_count);
99    }
100    UINT16_TO_BE_STREAM(p_len, len);
101    p_pkt->len = (p_data - p_start);
102    status = AVRC_STS_NO_ERROR;
103
104    return status;
105}
106
107/*******************************************************************************
108**
109** Function         avrc_bld_list_app_settings_attr_rsp
110**
111** Description      This function builds the List Application Settings Attribute
112**                  response.
113**
114** Returns          AVRC_STS_NO_ERROR, if the response is built successfully
115**                  Otherwise, the error code.
116**
117*******************************************************************************/
118static tAVRC_STS avrc_bld_list_app_settings_attr_rsp (tAVRC_LIST_APP_ATTR_RSP *p_rsp, BT_HDR *p_pkt)
119{
120    UINT8   *p_data, *p_start, *p_len, *p_num;
121    UINT16  len = 0;
122    UINT8   xx;
123
124    AVRC_TRACE_API0("avrc_bld_list_app_settings_attr_rsp");
125    /* get the existing length, if any, and also the num attributes */
126    p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
127    p_data = p_len = p_start + 2; /* pdu + rsvd */
128
129    BE_STREAM_TO_UINT16(len, p_data);
130    p_num = p_data;
131    if (len == 0)
132    {
133        /* first time initialize the attribute count */
134        *p_num = 0;
135        p_data++;
136    }
137    else
138    {
139        p_data = p_start + p_pkt->len;
140    }
141
142    for (xx=0; xx<p_rsp->num_attr; xx++)
143    {
144        if(AVRC_IsValidPlayerAttr(p_rsp->attrs[xx]))
145        {
146            (*p_num)++;
147            UINT8_TO_BE_STREAM(p_data, p_rsp->attrs[xx]);
148        }
149    }
150
151    len = *p_num + 1;
152    UINT16_TO_BE_STREAM(p_len, len);
153    p_pkt->len = (p_data - p_start);
154
155    return AVRC_STS_NO_ERROR;
156}
157
158/*******************************************************************************
159**
160** Function         avrc_bld_list_app_settings_values_rsp
161**
162** Description      This function builds the List Application Setting Values
163**                  response.
164**
165** Returns          AVRC_STS_NO_ERROR, if the response is built successfully
166**                  Otherwise, the error code.
167**
168*******************************************************************************/
169static tAVRC_STS avrc_bld_list_app_settings_values_rsp (tAVRC_LIST_APP_VALUES_RSP *p_rsp,
170    BT_HDR *p_pkt)
171{
172    UINT8   *p_data, *p_start, *p_len, *p_num;
173    UINT8   xx;
174    UINT16  len;
175
176    AVRC_TRACE_API0("avrc_bld_list_app_settings_values_rsp");
177
178    p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
179    p_data = p_len = p_start + 2; /* pdu + rsvd */
180
181    /* get the existing length, if any, and also the num attributes */
182    BE_STREAM_TO_UINT16(len, p_data);
183    p_num = p_data;
184    /* first time initialize the attribute count */
185    if (len == 0)
186    {
187        *p_num = p_rsp->num_val;
188        p_data++;
189    }
190    else
191    {
192        p_data = p_start + p_pkt->len;
193        *p_num += p_rsp->num_val;
194    }
195
196
197    for (xx=0; xx<p_rsp->num_val; xx++)
198    {
199        UINT8_TO_BE_STREAM(p_data, p_rsp->vals[xx]);
200    }
201
202    len = *p_num + 1;
203    UINT16_TO_BE_STREAM(p_len, len);
204    p_pkt->len = (p_data - p_start);
205    return AVRC_STS_NO_ERROR;
206}
207
208/*******************************************************************************
209**
210** Function         avrc_bld_get_cur_app_setting_value_rsp
211**
212** Description      This function builds the Get Current Application Setting Value
213**                  response.
214**
215** Returns          AVRC_STS_NO_ERROR, if the response is built successfully
216**                  Otherwise, the error code.
217**
218*******************************************************************************/
219static tAVRC_STS avrc_bld_get_cur_app_setting_value_rsp (tAVRC_GET_CUR_APP_VALUE_RSP *p_rsp,
220    BT_HDR *p_pkt)
221{
222    UINT8   *p_data, *p_start, *p_len, *p_count;
223    UINT16  len;
224    UINT8   xx;
225
226    if (!p_rsp->p_vals)
227    {
228        AVRC_TRACE_ERROR0("avrc_bld_get_cur_app_setting_value_rsp NULL parameter");
229        return AVRC_STS_BAD_PARAM;
230    }
231
232    AVRC_TRACE_API0("avrc_bld_get_cur_app_setting_value_rsp");
233    /* get the existing length, if any, and also the num attributes */
234    p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
235    p_data = p_len = p_start + 2; /* pdu + rsvd */
236
237    BE_STREAM_TO_UINT16(len, p_data);
238    p_count = p_data;
239    if (len == 0)
240    {
241        /* first time initialize the attribute count */
242        *p_count = 0;
243        p_data++;
244    }
245    else
246    {
247        p_data = p_start + p_pkt->len;
248    }
249
250    for (xx=0; xx<p_rsp->num_val; xx++)
251    {
252        if (avrc_is_valid_player_attrib_value(p_rsp->p_vals[xx].attr_id, p_rsp->p_vals[xx].attr_val))
253        {
254            (*p_count)++;
255            UINT8_TO_BE_STREAM(p_data, p_rsp->p_vals[xx].attr_id);
256            UINT8_TO_BE_STREAM(p_data, p_rsp->p_vals[xx].attr_val);
257        }
258    }
259    len = ((*p_count) << 1) + 1;
260    UINT16_TO_BE_STREAM(p_len, len);
261    p_pkt->len = (p_data - p_start);
262
263    return AVRC_STS_NO_ERROR;
264}
265
266/*******************************************************************************
267**
268** Function         avrc_bld_set_app_setting_value_rsp
269**
270** Description      This function builds the Set Application Setting Value
271**                  response.
272**
273** Returns          AVRC_STS_NO_ERROR, if the response is built successfully
274**                  Otherwise, the error code.
275**
276*******************************************************************************/
277static tAVRC_STS avrc_bld_set_app_setting_value_rsp (tAVRC_RSP *p_rsp, BT_HDR *p_pkt)
278{
279    /* nothing to be added. */
280    AVRC_TRACE_API0("avrc_bld_set_app_setting_value_rsp");
281    return AVRC_STS_NO_ERROR;
282}
283
284/*******************************************************************************
285**
286** Function         avrc_bld_app_setting_text_rsp
287**
288** Description      This function builds the Get Application Settings Attribute Text
289**                  or Get Application Settings Value Text response.
290**
291** Returns          AVRC_STS_NO_ERROR, if the response is built successfully
292**                  Otherwise, the error code.
293**
294*******************************************************************************/
295static tAVRC_STS avrc_bld_app_setting_text_rsp (tAVRC_GET_APP_ATTR_TXT_RSP *p_rsp, BT_HDR *p_pkt)
296{
297    UINT8   *p_data, *p_start, *p_len, *p_count;
298    UINT16  len, len_left;
299    UINT8   xx;
300    tAVRC_STS   sts = AVRC_STS_NO_ERROR;
301    UINT8       num_added = 0;
302
303    if (!p_rsp->p_attrs)
304    {
305        AVRC_TRACE_ERROR0("avrc_bld_app_setting_text_rsp NULL parameter");
306        return AVRC_STS_BAD_PARAM;
307    }
308    /* get the existing length, if any, and also the num attributes */
309    p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
310    p_data = p_len = p_start + 2; /* pdu + rsvd */
311    len_left = GKI_get_buf_size(p_pkt) - BT_HDR_SIZE - p_pkt->offset - p_pkt->len;
312
313    BE_STREAM_TO_UINT16(len, p_data);
314    p_count = p_data;
315
316    if (len == 0)
317    {
318        *p_count = 0;
319        p_data++;
320    }
321    else
322    {
323        p_data = p_start + p_pkt->len;
324    }
325
326    for (xx=0; xx<p_rsp->num_attr; xx++)
327    {
328        if  (len_left < (p_rsp->p_attrs[xx].str_len + 4))
329        {
330            AVRC_TRACE_ERROR3("avrc_bld_app_setting_text_rsp out of room (str_len:%d, left:%d)",
331                xx, p_rsp->p_attrs[xx].str_len, len_left);
332            p_rsp->num_attr = num_added;
333            sts = AVRC_STS_INTERNAL_ERR;
334            break;
335        }
336        if ( !p_rsp->p_attrs[xx].str_len || !p_rsp->p_attrs[xx].p_str )
337        {
338            AVRC_TRACE_ERROR1("avrc_bld_app_setting_text_rsp NULL attr text[%d]", xx);
339            continue;
340        }
341        UINT8_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].attr_id);
342        UINT16_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].charset_id);
343        UINT8_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].str_len);
344        ARRAY_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].p_str, p_rsp->p_attrs[xx].str_len);
345        (*p_count)++;
346        num_added++;
347    }
348    len = p_data - p_count;
349    UINT16_TO_BE_STREAM(p_len, len);
350    p_pkt->len = (p_data - p_start);
351
352    return sts;
353}
354
355/*******************************************************************************
356**
357** Function         avrc_bld_get_app_setting_attr_text_rsp
358**
359** Description      This function builds the Get Application Setting Attribute Text
360**                  response.
361**
362** Returns          AVRC_STS_NO_ERROR, if the response is built successfully
363**                  Otherwise, the error code.
364**
365*******************************************************************************/
366static tAVRC_STS avrc_bld_get_app_setting_attr_text_rsp (tAVRC_GET_APP_ATTR_TXT_RSP *p_rsp,
367    BT_HDR *p_pkt)
368{
369    AVRC_TRACE_API0("avrc_bld_get_app_setting_attr_text_rsp");
370    return avrc_bld_app_setting_text_rsp(p_rsp, p_pkt);
371}
372
373/*******************************************************************************
374**
375** Function         avrc_bld_get_app_setting_value_text_rsp
376**
377** Description      This function builds the Get Application Setting Value Text
378**                  response.
379**
380** Returns          AVRC_STS_NO_ERROR, if the response is built successfully
381**                  Otherwise, the error code.
382**
383*******************************************************************************/
384static tAVRC_STS avrc_bld_get_app_setting_value_text_rsp (tAVRC_GET_APP_ATTR_TXT_RSP *p_rsp,
385    BT_HDR *p_pkt)
386{
387    AVRC_TRACE_API0("avrc_bld_get_app_setting_value_text_rsp");
388    return avrc_bld_app_setting_text_rsp(p_rsp, p_pkt);
389}
390
391/*******************************************************************************
392**
393** Function         avrc_bld_inform_charset_rsp
394**
395** Description      This function builds the Inform Displayable Character Set
396**                  response.
397**
398** Returns          AVRC_STS_NO_ERROR, if the response is built successfully
399**                  Otherwise, the error code.
400**
401*******************************************************************************/
402static tAVRC_STS avrc_bld_inform_charset_rsp (tAVRC_RSP *p_rsp, BT_HDR *p_pkt)
403{
404    /* nothing to be added. */
405    AVRC_TRACE_API0("avrc_bld_inform_charset_rsp");
406    return AVRC_STS_NO_ERROR;
407}
408
409/*******************************************************************************
410**
411** Function         avrc_bld_inform_battery_status_rsp
412**
413** Description      This function builds the Inform Battery Status
414**                  response.
415**
416** Returns          AVRC_STS_NO_ERROR, if the response is built successfully
417**                  Otherwise, the error code.
418**
419*******************************************************************************/
420static tAVRC_STS avrc_bld_inform_battery_status_rsp (tAVRC_RSP *p_rsp, BT_HDR *p_pkt)
421{
422    /* nothing to be added. */
423    AVRC_TRACE_API0("avrc_bld_inform_battery_status_rsp");
424    return AVRC_STS_NO_ERROR;
425}
426
427/*******************************************************************************
428**
429** Function         avrc_bld_get_elem_attrs_rsp
430**
431** Description      This function builds the Get Element Attributes
432**                  response.
433**
434** Returns          AVRC_STS_NO_ERROR, if the response is built successfully
435**                  Otherwise, the error code.
436**
437*******************************************************************************/
438static tAVRC_STS avrc_bld_get_elem_attrs_rsp (tAVRC_GET_ELEM_ATTRS_RSP *p_rsp, BT_HDR *p_pkt)
439{
440    UINT8   *p_data, *p_start, *p_len, *p_count;
441    UINT16  len;
442    UINT8   xx;
443
444    AVRC_TRACE_API0("avrc_bld_get_elem_attrs_rsp");
445    if (!p_rsp->p_attrs)
446    {
447        AVRC_TRACE_ERROR0("avrc_bld_get_elem_attrs_rsp NULL parameter");
448        return AVRC_STS_BAD_PARAM;
449    }
450
451    /* get the existing length, if any, and also the num attributes */
452    p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
453    p_data = p_len = p_start + 2; /* pdu + rsvd */
454
455    BE_STREAM_TO_UINT16(len, p_data);
456    p_count = p_data;
457
458    if (len == 0)
459    {
460        *p_count = 0;
461        p_data++;
462    }
463    else
464    {
465        p_data = p_start + p_pkt->len;
466    }
467
468    for (xx=0; xx<p_rsp->num_attr; xx++)
469    {
470        if (!AVRC_IS_VALID_MEDIA_ATTRIBUTE(p_rsp->p_attrs[xx].attr_id))
471        {
472            AVRC_TRACE_ERROR2("avrc_bld_get_elem_attrs_rsp invalid attr id[%d]: %d", xx, p_rsp->p_attrs[xx].attr_id);
473            continue;
474        }
475        if ( !p_rsp->p_attrs[xx].name.p_str )
476        {
477            p_rsp->p_attrs[xx].name.str_len = 0;
478        }
479        UINT32_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].attr_id);
480        UINT16_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].name.charset_id);
481        UINT16_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].name.str_len);
482        ARRAY_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].name.p_str, p_rsp->p_attrs[xx].name.str_len);
483        (*p_count)++;
484    }
485    len = p_data - p_count;
486    UINT16_TO_BE_STREAM(p_len, len);
487    p_pkt->len = (p_data - p_start);
488    return AVRC_STS_NO_ERROR;
489}
490
491/*******************************************************************************
492**
493** Function         avrc_bld_get_play_status_rsp
494**
495** Description      This function builds the Get Play Status
496**                  response.
497**
498** Returns          AVRC_STS_NO_ERROR, if the response is built successfully
499**                  Otherwise, the error code.
500**
501*******************************************************************************/
502static tAVRC_STS avrc_bld_get_play_status_rsp (tAVRC_GET_PLAY_STATUS_RSP *p_rsp, BT_HDR *p_pkt)
503{
504    UINT8   *p_data, *p_start;
505
506    AVRC_TRACE_API0("avrc_bld_get_play_status_rsp");
507    p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
508    p_data = p_start + 2;
509
510    /* add fixed lenth - song len(4) + song position(4) + status(1) */
511    UINT16_TO_BE_STREAM(p_data, 9);
512    UINT32_TO_BE_STREAM(p_data, p_rsp->song_len);
513    UINT32_TO_BE_STREAM(p_data, p_rsp->song_pos);
514    UINT8_TO_BE_STREAM(p_data, p_rsp->play_status);
515    p_pkt->len = (p_data - p_start);
516
517    return AVRC_STS_NO_ERROR;
518}
519
520/*******************************************************************************
521**
522** Function         avrc_bld_notify_rsp
523**
524** Description      This function builds the Notification response.
525**
526** Returns          AVRC_STS_NO_ERROR, if the response is built successfully
527**                  Otherwise, the error code.
528**
529*******************************************************************************/
530static tAVRC_STS avrc_bld_notify_rsp (tAVRC_REG_NOTIF_RSP *p_rsp, BT_HDR *p_pkt)
531{
532    UINT8   *p_data, *p_start;
533    UINT8   *p_len;
534    UINT16  len = 0;
535    UINT8   xx;
536    tAVRC_STS status = AVRC_STS_NO_ERROR;
537
538    AVRC_TRACE_API0("avrc_bld_notify_rsp");
539
540    p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
541    p_data = p_len = p_start + 2; /* pdu + rsvd */
542    p_data += 2;
543
544    UINT8_TO_BE_STREAM(p_data, p_rsp->event_id);
545    switch (p_rsp->event_id)
546    {
547    case AVRC_EVT_PLAY_STATUS_CHANGE:       /* 0x01 */
548        /* p_rsp->param.play_status >= AVRC_PLAYSTATE_STOPPED is always TRUE */
549        if ((p_rsp->param.play_status <= AVRC_PLAYSTATE_REV_SEEK) ||
550            (p_rsp->param.play_status == AVRC_PLAYSTATE_ERROR) )
551        {
552            UINT8_TO_BE_STREAM(p_data, p_rsp->param.play_status);
553            len = 2;
554        }
555        else
556        {
557            AVRC_TRACE_ERROR0("bad play state");
558            status = AVRC_STS_BAD_PARAM;
559        }
560        break;
561
562    case AVRC_EVT_TRACK_CHANGE:             /* 0x02 */
563        ARRAY_TO_BE_STREAM(p_data, p_rsp->param.track, AVRC_UID_SIZE);
564        len = (UINT8)(AVRC_UID_SIZE + 1);
565        break;
566
567    case AVRC_EVT_TRACK_REACHED_END:        /* 0x03 */
568    case AVRC_EVT_TRACK_REACHED_START:      /* 0x04 */
569        len = 1;
570        break;
571
572    case AVRC_EVT_PLAY_POS_CHANGED:         /* 0x05 */
573        UINT32_TO_BE_STREAM(p_data, p_rsp->param.play_pos);
574        len = 5;
575        break;
576
577    case AVRC_EVT_BATTERY_STATUS_CHANGE:    /* 0x06 */
578        if (AVRC_IS_VALID_BATTERY_STATUS(p_rsp->param.battery_status))
579        {
580            UINT8_TO_BE_STREAM(p_data, p_rsp->param.battery_status);
581            len = 2;
582        }
583        else
584        {
585            AVRC_TRACE_ERROR0("bad battery status");
586            status = AVRC_STS_BAD_PARAM;
587        }
588        break;
589
590    case AVRC_EVT_SYSTEM_STATUS_CHANGE:     /* 0x07 */
591        if (AVRC_IS_VALID_SYSTEM_STATUS(p_rsp->param.system_status))
592        {
593            UINT8_TO_BE_STREAM(p_data, p_rsp->param.system_status);
594            len = 2;
595        }
596        else
597        {
598            AVRC_TRACE_ERROR0("bad system status");
599            status = AVRC_STS_BAD_PARAM;
600        }
601        break;
602
603    case AVRC_EVT_APP_SETTING_CHANGE:       /* 0x08 */
604        if (p_rsp->param.player_setting.num_attr > AVRC_MAX_APP_SETTINGS)
605            p_rsp->param.player_setting.num_attr = AVRC_MAX_APP_SETTINGS;
606
607        if (p_rsp->param.player_setting.num_attr > 0)
608        {
609            UINT8_TO_BE_STREAM(p_data, p_rsp->param.player_setting.num_attr);
610            len = 2;
611            for (xx=0; xx<p_rsp->param.player_setting.num_attr; xx++)
612            {
613                if (avrc_is_valid_player_attrib_value(p_rsp->param.player_setting.attr_id[xx],
614                    p_rsp->param.player_setting.attr_value[xx]))
615                {
616                    UINT8_TO_BE_STREAM(p_data, p_rsp->param.player_setting.attr_id[xx]);
617                    UINT8_TO_BE_STREAM(p_data, p_rsp->param.player_setting.attr_value[xx]);
618                }
619                else
620                {
621                    AVRC_TRACE_ERROR0("bad player app seeting attribute or value");
622                    status = AVRC_STS_BAD_PARAM;
623                    break;
624                }
625                len += 2;
626            }
627        }
628        else
629            status = AVRC_STS_BAD_PARAM;
630        break;
631
632    default:
633        status = AVRC_STS_BAD_PARAM;
634        AVRC_TRACE_ERROR0("unknown event_id");
635    }
636
637    UINT16_TO_BE_STREAM(p_len, len);
638    p_pkt->len = (p_data - p_start);
639
640    return status;
641}
642
643/*******************************************************************************
644**
645** Function         avrc_bld_next_rsp
646**
647** Description      This function builds the Request Continue or Abort
648**                  response.
649**
650** Returns          AVRC_STS_NO_ERROR, if the response is built successfully
651**                  Otherwise, the error code.
652**
653*******************************************************************************/
654static tAVRC_STS avrc_bld_next_rsp (tAVRC_RSP *p_rsp, BT_HDR *p_pkt)
655{
656    /* nothing to be added. */
657    AVRC_TRACE_API0("avrc_bld_next_rsp");
658    return AVRC_STS_NO_ERROR;
659}
660
661/*******************************************************************************
662**
663** Function         avrc_bld_group_navigation_rsp
664**
665** Description      This function builds the Group Navigation
666**                  response.
667**
668** Returns          AVRC_STS_NO_ERROR, if the response is built successfully
669**                  Otherwise, the error code.
670**
671*******************************************************************************/
672tAVRC_STS avrc_bld_group_navigation_rsp (UINT16 navi_id, BT_HDR *p_pkt)
673{
674    UINT8   *p_data;
675
676    if (!AVRC_IS_VALID_GROUP(navi_id))
677    {
678        AVRC_TRACE_ERROR1("avrc_bld_group_navigation_rsp bad navigation op id: %d", navi_id);
679        return AVRC_STS_BAD_PARAM;
680    }
681
682    AVRC_TRACE_API0("avrc_bld_group_navigation_rsp");
683    p_data = (UINT8 *)(p_pkt+1) + p_pkt->offset;
684    UINT16_TO_BE_STREAM(p_data, navi_id);
685    p_pkt->len = 2;
686    return AVRC_STS_NO_ERROR;
687}
688
689/*******************************************************************************
690**
691** Function         avrc_bld_rejected_rsp
692**
693** Description      This function builds the General Response response.
694**
695** Returns          AVRC_STS_NO_ERROR, if the response is built successfully
696**                  Otherwise, the error code.
697**
698*******************************************************************************/
699static tAVRC_STS avrc_bld_rejected_rsp( tAVRC_RSP *p_rsp, BT_HDR *p_pkt )
700{
701    UINT8 *p_data, *p_start;
702
703    AVRC_TRACE_API2("avrc_bld_rejected_rsp: status=%d, pdu:x%x", p_rsp->status, p_rsp->pdu);
704
705    p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
706    p_data = p_start + 2;
707    AVRC_TRACE_DEBUG1("pdu:x%x", *p_start);
708
709    UINT16_TO_BE_STREAM(p_data, 1);
710    UINT8_TO_BE_STREAM(p_data, p_rsp->status);
711    p_pkt->len = p_data - p_start;
712
713    return AVRC_STS_NO_ERROR;
714}
715
716/*******************************************************************************
717**
718** Function         avrc_bld_init_rsp_buffer
719**
720** Description      This function initializes the response buffer based on PDU
721**
722** Returns          NULL, if no GKI buffer or failure to build the message.
723**                  Otherwise, the GKI buffer that contains the initialized message.
724**
725*******************************************************************************/
726static BT_HDR *avrc_bld_init_rsp_buffer(tAVRC_RESPONSE *p_rsp)
727{
728    UINT16 offset = AVRC_MSG_PASS_THRU_OFFSET, chnl = AVCT_DATA_CTRL, len=AVRC_META_CMD_POOL_SIZE;
729    BT_HDR *p_pkt=NULL;
730    UINT8  opcode = avrc_opcode_from_pdu(p_rsp->pdu);
731
732    AVRC_TRACE_API3("avrc_bld_init_rsp_buffer: pdu=%x, opcode=%x/%x", p_rsp->pdu, opcode,
733        p_rsp->rsp.opcode);
734    if (opcode != p_rsp->rsp.opcode && p_rsp->rsp.status != AVRC_STS_NO_ERROR &&
735        avrc_is_valid_opcode(p_rsp->rsp.opcode))
736    {
737        opcode = p_rsp->rsp.opcode;
738        AVRC_TRACE_API1("opcode=%x", opcode);
739    }
740
741    switch (opcode)
742    {
743    case AVRC_OP_PASS_THRU:
744        offset  = AVRC_MSG_PASS_THRU_OFFSET;
745        break;
746
747    case AVRC_OP_VENDOR:
748        offset  = AVRC_MSG_VENDOR_OFFSET;
749        if (p_rsp->pdu == AVRC_PDU_GET_ELEMENT_ATTR)
750            len     = AVRC_BROWSE_POOL_SIZE;
751        break;
752    }
753
754    /* allocate and initialize the buffer */
755    p_pkt = (BT_HDR *)GKI_getbuf(len);
756    if (p_pkt)
757    {
758        UINT8 *p_data, *p_start;
759
760        p_pkt->layer_specific = chnl;
761        p_pkt->event    = opcode;
762        p_pkt->offset   = offset;
763        p_data = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
764        p_start = p_data;
765
766        /* pass thru - group navigation - has a two byte op_id, so dont do it here */
767        if (opcode != AVRC_OP_PASS_THRU)
768            *p_data++ = p_rsp->pdu;
769
770        switch (opcode)
771        {
772        case AVRC_OP_VENDOR:
773            /* reserved 0, packet_type 0 */
774            UINT8_TO_BE_STREAM(p_data, 0);
775            /* continue to the next "case to add length */
776            /* add fixed lenth - 0 */
777            UINT16_TO_BE_STREAM(p_data, 0);
778            break;
779        }
780
781        p_pkt->len = (p_data - p_start);
782    }
783    p_rsp->rsp.opcode = opcode;
784    return p_pkt;
785}
786
787/*******************************************************************************
788**
789** Function         AVRC_BldResponse
790**
791** Description      This function builds the given AVRCP response to the given
792**                  GKI buffer
793**
794** Returns          AVRC_STS_NO_ERROR, if the response is built successfully
795**                  Otherwise, the error code.
796**
797*******************************************************************************/
798tAVRC_STS AVRC_BldResponse( UINT8 handle, tAVRC_RESPONSE *p_rsp, BT_HDR **pp_pkt)
799{
800    tAVRC_STS status = AVRC_STS_BAD_PARAM;
801    BT_HDR *p_pkt;
802    BOOLEAN alloc = FALSE;
803
804    if (!p_rsp || !pp_pkt)
805    {
806        AVRC_TRACE_API2("AVRC_BldResponse. Invalid parameters passed. p_rsp=%p, pp_pkt=%p",
807            p_rsp, pp_pkt);
808        return AVRC_STS_BAD_PARAM;
809    }
810
811    if (*pp_pkt == NULL)
812    {
813        if ((*pp_pkt = avrc_bld_init_rsp_buffer(p_rsp)) == NULL)
814        {
815            AVRC_TRACE_API0("AVRC_BldResponse: Failed to initialize response buffer");
816            return AVRC_STS_INTERNAL_ERR;
817        }
818        alloc = TRUE;
819    }
820    status = AVRC_STS_NO_ERROR;
821    p_pkt = *pp_pkt;
822
823    AVRC_TRACE_API2("AVRC_BldResponse: pdu=%x status=%x", p_rsp->rsp.pdu, p_rsp->rsp.status);
824    if (p_rsp->rsp.status != AVRC_STS_NO_ERROR)
825    {
826        return( avrc_bld_rejected_rsp(&p_rsp->rsp, p_pkt) );
827    }
828
829    switch (p_rsp->pdu)
830    {
831    case AVRC_PDU_NEXT_GROUP:
832    case AVRC_PDU_PREV_GROUP:
833        status = avrc_bld_group_navigation_rsp(p_rsp->pdu, p_pkt);
834        break;
835
836    case AVRC_PDU_GET_CAPABILITIES:
837        status = avrc_bld_get_capability_rsp(&p_rsp->get_caps, p_pkt);
838        break;
839
840    case AVRC_PDU_LIST_PLAYER_APP_ATTR:
841        status = avrc_bld_list_app_settings_attr_rsp(&p_rsp->list_app_attr, p_pkt);
842        break;
843
844    case AVRC_PDU_LIST_PLAYER_APP_VALUES:
845        status = avrc_bld_list_app_settings_values_rsp(&p_rsp->list_app_values, p_pkt);
846        break;
847
848    case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE:
849        status = avrc_bld_get_cur_app_setting_value_rsp(&p_rsp->get_cur_app_val, p_pkt);
850        break;
851
852    case AVRC_PDU_SET_PLAYER_APP_VALUE:
853        status = avrc_bld_set_app_setting_value_rsp(&p_rsp->set_app_val, p_pkt);
854        break;
855
856    case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT:
857        status = avrc_bld_get_app_setting_attr_text_rsp(&p_rsp->get_app_attr_txt, p_pkt);
858        break;
859
860    case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT:
861        status = avrc_bld_get_app_setting_value_text_rsp(&p_rsp->get_app_val_txt, p_pkt);
862        break;
863
864    case AVRC_PDU_INFORM_DISPLAY_CHARSET:
865        status = avrc_bld_inform_charset_rsp(&p_rsp->inform_charset, p_pkt);
866        break;
867
868    case AVRC_PDU_INFORM_BATTERY_STAT_OF_CT:
869        status = avrc_bld_inform_battery_status_rsp(&p_rsp->inform_battery_status, p_pkt);
870        break;
871
872    case AVRC_PDU_GET_ELEMENT_ATTR:
873        status = avrc_bld_get_elem_attrs_rsp(&p_rsp->get_elem_attrs, p_pkt);
874        break;
875
876    case AVRC_PDU_GET_PLAY_STATUS:
877        status = avrc_bld_get_play_status_rsp(&p_rsp->get_play_status, p_pkt);
878        break;
879
880    case AVRC_PDU_REGISTER_NOTIFICATION:
881        status = avrc_bld_notify_rsp(&p_rsp->reg_notif, p_pkt);
882        break;
883
884    case AVRC_PDU_REQUEST_CONTINUATION_RSP:     /*        0x40 */
885        status = avrc_bld_next_rsp(&p_rsp->continu, p_pkt);
886        break;
887
888    case AVRC_PDU_ABORT_CONTINUATION_RSP:       /*          0x41 */
889        status = avrc_bld_next_rsp(&p_rsp->abort, p_pkt);
890        break;
891    }
892
893    if (alloc && (status != AVRC_STS_NO_ERROR) )
894    {
895        GKI_freebuf(p_pkt);
896        *pp_pkt = NULL;
897    }
898    AVRC_TRACE_API1("AVRC_BldResponse: returning %d", status);
899    return status;
900}
901
902#endif /* (AVRC_METADATA_INCLUDED == TRUE)*/
903
904