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