1/******************************************************************************
2 *
3 *  Copyright (C) 2006-2013 Broadcom Corporation
4 *
5 *  Licensed under the Apache License, Version 2.0 (the "License");
6 *  you may not use this file except in compliance with the License.
7 *  You may obtain a copy of the License at:
8 *
9 *  http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 *
17 ******************************************************************************/
18#include <string.h>
19
20#include "bt_common.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
30#if (AVRC_METADATA_INCLUDED == TRUE)
31
32/*******************************************************************************
33**
34** Function         avrc_pars_vendor_rsp
35**
36** Description      This function parses the vendor specific commands defined by
37**                  Bluetooth SIG
38**
39** Returns          AVRC_STS_NO_ERROR, if the message in p_data is parsed successfully.
40**                  Otherwise, the error code defined by AVRCP 1.4
41**
42*******************************************************************************/
43static tAVRC_STS avrc_pars_vendor_rsp(tAVRC_MSG_VENDOR *p_msg, tAVRC_RESPONSE *p_result)
44{
45    tAVRC_STS  status = AVRC_STS_NO_ERROR;
46    UINT8   *p;
47    UINT16  len;
48#if (AVRC_ADV_CTRL_INCLUDED == TRUE)
49    UINT8 eventid=0;
50#endif
51
52    /* Check the vendor data */
53    if (p_msg->vendor_len == 0)
54        return AVRC_STS_NO_ERROR;
55    if (p_msg->p_vendor_data == NULL)
56        return AVRC_STS_INTERNAL_ERR;
57
58    p = p_msg->p_vendor_data;
59    BE_STREAM_TO_UINT8 (p_result->pdu, p);
60    p++; /* skip the reserved/packe_type byte */
61    BE_STREAM_TO_UINT16 (len, p);
62    AVRC_TRACE_DEBUG("%s ctype:0x%x pdu:0x%x, len:%d/0x%x",
63                     __func__, p_msg->hdr.ctype, p_result->pdu, len, len);
64    if (p_msg->hdr.ctype == AVRC_RSP_REJ)
65    {
66        p_result->rsp.status = *p;
67        return p_result->rsp.status;
68    }
69
70    switch (p_result->pdu)
71    {
72    /* case AVRC_PDU_REQUEST_CONTINUATION_RSP: 0x40 */
73    /* case AVRC_PDU_ABORT_CONTINUATION_RSP:   0x41 */
74
75#if (AVRC_ADV_CTRL_INCLUDED == TRUE)
76    case AVRC_PDU_SET_ABSOLUTE_VOLUME:      /* 0x50 */
77        if (len != 1)
78            status = AVRC_STS_INTERNAL_ERR;
79        else
80        {
81            BE_STREAM_TO_UINT8 (p_result->volume.volume, p);
82        }
83        break;
84#endif /* (AVRC_ADV_CTRL_INCLUDED == TRUE) */
85
86    case AVRC_PDU_REGISTER_NOTIFICATION:    /* 0x31 */
87#if (AVRC_ADV_CTRL_INCLUDED == TRUE)
88        BE_STREAM_TO_UINT8 (eventid, p);
89        if(AVRC_EVT_VOLUME_CHANGE==eventid
90            && (AVRC_RSP_CHANGED==p_msg->hdr.ctype || AVRC_RSP_INTERIM==p_msg->hdr.ctype
91            || AVRC_RSP_REJ==p_msg->hdr.ctype || AVRC_RSP_NOT_IMPL==p_msg->hdr.ctype))
92        {
93            p_result->reg_notif.status=p_msg->hdr.ctype;
94            p_result->reg_notif.event_id=eventid;
95            BE_STREAM_TO_UINT8 (p_result->reg_notif.param.volume, p);
96        }
97        AVRC_TRACE_DEBUG("%s PDU reg notif response:event %x, volume %x",
98                         __func__, eventid, p_result->reg_notif.param.volume);
99#endif /* (AVRC_ADV_CTRL_INCLUDED == TRUE) */
100        break;
101    default:
102        status = AVRC_STS_BAD_CMD;
103        break;
104    }
105
106    return status;
107}
108
109void avrc_parse_notification_rsp (UINT8 *p_stream, tAVRC_REG_NOTIF_RSP *p_rsp)
110{
111    BE_STREAM_TO_UINT8(p_rsp->event_id, p_stream);
112    switch (p_rsp->event_id)
113    {
114        case AVRC_EVT_PLAY_STATUS_CHANGE:
115            BE_STREAM_TO_UINT8(p_rsp->param.play_status, p_stream);
116            break;
117
118        case AVRC_EVT_TRACK_CHANGE:
119            BE_STREAM_TO_ARRAY(p_stream, p_rsp->param.track, 8);
120            break;
121
122        case AVRC_EVT_APP_SETTING_CHANGE:
123            BE_STREAM_TO_UINT8(p_rsp->param.player_setting.num_attr, p_stream);
124            for (int index = 0; index < p_rsp->param.player_setting.num_attr; index++)
125            {
126                BE_STREAM_TO_UINT8(p_rsp->param.player_setting.attr_id[index], p_stream);
127                BE_STREAM_TO_UINT8(p_rsp->param.player_setting.attr_value[index], p_stream);
128            }
129            break;
130
131        case AVRC_EVT_NOW_PLAYING_CHANGE:
132            break;
133
134        case AVRC_EVT_AVAL_PLAYERS_CHANGE:
135            break;
136
137        case AVRC_EVT_ADDR_PLAYER_CHANGE:
138            break;
139
140        case AVRC_EVT_UIDS_CHANGE:
141            break;
142
143        case AVRC_EVT_TRACK_REACHED_END:
144        case AVRC_EVT_TRACK_REACHED_START:
145        case AVRC_EVT_PLAY_POS_CHANGED:
146        case AVRC_EVT_BATTERY_STATUS_CHANGE:
147        case AVRC_EVT_SYSTEM_STATUS_CHANGE:
148        default:
149            break;
150    }
151}
152
153#if (AVRC_CTLR_INCLUDED == TRUE)
154/*******************************************************************************
155**
156** Function         avrc_ctrl_pars_vendor_rsp
157**
158** Description      This function parses the vendor specific commands defined by
159**                  Bluetooth SIG
160**
161** Returns          AVRC_STS_NO_ERROR, if the message in p_data is parsed successfully.
162**                  Otherwise, the error code defined by AVRCP 1.4
163**
164*******************************************************************************/
165static tAVRC_STS avrc_ctrl_pars_vendor_rsp(
166    tAVRC_MSG_VENDOR *p_msg, tAVRC_RESPONSE *p_result, UINT8* p_buf, UINT16* buf_len)
167{
168    UINT8   *p = p_msg->p_vendor_data;
169    BE_STREAM_TO_UINT8 (p_result->pdu, p);
170    p++; /* skip the reserved/packe_type byte */
171
172    UINT16  len;
173    BE_STREAM_TO_UINT16 (len, p);
174    AVRC_TRACE_DEBUG("%s ctype:0x%x pdu:0x%x, len:%d",
175                     __func__, p_msg->hdr.ctype, p_result->pdu, len);
176    /* Todo: Issue in handling reject, check */
177    if (p_msg->hdr.ctype == AVRC_RSP_REJ)
178    {
179        p_result->rsp.status = *p;
180        return p_result->rsp.status;
181    }
182
183    /* TODO: Break the big switch into functions. */
184    switch (p_result->pdu)
185    {
186    /* case AVRC_PDU_REQUEST_CONTINUATION_RSP: 0x40 */
187    /* case AVRC_PDU_ABORT_CONTINUATION_RSP:   0x41 */
188
189    case AVRC_PDU_REGISTER_NOTIFICATION:
190        avrc_parse_notification_rsp(p, &p_result->reg_notif);
191        break;
192
193    case AVRC_PDU_GET_CAPABILITIES:
194        if (len == 0)
195        {
196            p_result->get_caps.count = 0;
197            p_result->get_caps.capability_id = 0;
198            break;
199        }
200        BE_STREAM_TO_UINT8(p_result->get_caps.capability_id, p);
201        BE_STREAM_TO_UINT8(p_result->get_caps.count, p);
202        AVRC_TRACE_DEBUG("%s cap id = %d, cap_count = %d ",
203                         __func__, p_result->get_caps.capability_id, p_result->get_caps.count);
204        if (p_result->get_caps.capability_id == AVRC_CAP_COMPANY_ID)
205        {
206            for(int xx = 0; ((xx < p_result->get_caps.count) && (xx < AVRC_CAP_MAX_NUM_COMP_ID));
207                xx++)
208            {
209                BE_STREAM_TO_UINT24(p_result->get_caps.param.company_id[xx], p);
210            }
211        }
212        else if (p_result->get_caps.capability_id == AVRC_CAP_EVENTS_SUPPORTED)
213        {
214            for(int xx = 0; ((xx < p_result->get_caps.count) && (xx < AVRC_CAP_MAX_NUM_EVT_ID));
215                xx++)
216            {
217                BE_STREAM_TO_UINT8(p_result->get_caps.param.event_id[xx], p);
218            }
219        }
220        break;
221
222    case AVRC_PDU_LIST_PLAYER_APP_ATTR:
223        if (len == 0)
224        {
225            p_result->list_app_attr.num_attr = 0;
226            break;
227        }
228        BE_STREAM_TO_UINT8(p_result->list_app_attr.num_attr, p);
229        AVRC_TRACE_DEBUG("%s attr count = %d ", __func__, p_result->list_app_attr.num_attr);
230        for(int xx = 0; xx < p_result->list_app_attr.num_attr; xx++)
231        {
232            BE_STREAM_TO_UINT8(p_result->list_app_attr.attrs[xx], p);
233        }
234        break;
235
236    case AVRC_PDU_LIST_PLAYER_APP_VALUES:
237        if (len == 0)
238        {
239            p_result->list_app_values.num_val = 0;
240            break;
241        }
242        BE_STREAM_TO_UINT8(p_result->list_app_values.num_val, p);
243        AVRC_TRACE_DEBUG("%s value count = %d ", __func__, p_result->list_app_values.num_val);
244        for(int xx = 0; xx < p_result->list_app_values.num_val; xx++)
245        {
246            BE_STREAM_TO_UINT8(p_result->list_app_values.vals[xx], p);
247        }
248        break;
249
250    case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE:
251    {
252        if (len == 0)
253        {
254            p_result->get_cur_app_val.num_val = 0;
255            break;
256        }
257        BE_STREAM_TO_UINT8(p_result->get_cur_app_val.num_val, p);
258        tAVRC_APP_SETTING *app_sett =
259            (tAVRC_APP_SETTING*)osi_malloc(p_result->get_cur_app_val.num_val*sizeof(tAVRC_APP_SETTING));
260        AVRC_TRACE_DEBUG("%s attr count = %d ", __func__, p_result->get_cur_app_val.num_val);
261        for (int xx = 0; xx < p_result->get_cur_app_val.num_val; xx++)
262        {
263            BE_STREAM_TO_UINT8(app_sett[xx].attr_id, p);
264            BE_STREAM_TO_UINT8(app_sett[xx].attr_val, p);
265        }
266        p_result->get_cur_app_val.p_vals = app_sett;
267    }
268        break;
269
270    case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT:
271    {
272        tAVRC_APP_SETTING_TEXT   *p_setting_text;
273        UINT8                    num_attrs;
274
275        if (len == 0)
276        {
277            p_result->get_app_attr_txt.num_attr = 0;
278            break;
279        }
280        BE_STREAM_TO_UINT8(num_attrs, p);
281        AVRC_TRACE_DEBUG("%s attr count = %d ", __func__, p_result->get_app_attr_txt.num_attr);
282        p_result->get_app_attr_txt.num_attr = num_attrs;
283        p_setting_text = (tAVRC_APP_SETTING_TEXT*)osi_malloc(num_attrs * sizeof(tAVRC_APP_SETTING_TEXT));
284        for (int xx = 0; xx < num_attrs; xx++)
285        {
286            BE_STREAM_TO_UINT8(p_result->get_app_attr_txt.p_attrs[xx].attr_id, p);
287            BE_STREAM_TO_UINT16(p_result->get_app_attr_txt.p_attrs[xx].charset_id, p);
288            BE_STREAM_TO_UINT8(p_result->get_app_attr_txt.p_attrs[xx].str_len, p);
289            if (p_result->get_app_attr_txt.p_attrs[xx].str_len != 0)
290            {
291                UINT8 *p_str = (UINT8 *)osi_malloc(p_result->get_app_attr_txt.p_attrs[xx].str_len);
292                BE_STREAM_TO_ARRAY(p, p_str, p_result->get_app_attr_txt.p_attrs[xx].str_len);
293                p_result->get_app_attr_txt.p_attrs[xx].p_str = p_str;
294            } else {
295                p_result->get_app_attr_txt.p_attrs[xx].p_str = NULL;
296            }
297        }
298    }
299        break;
300
301    case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT:
302    {
303        tAVRC_APP_SETTING_TEXT   *p_setting_text;
304        UINT8                    num_vals;
305
306        if (len == 0)
307        {
308            p_result->get_app_val_txt.num_attr = 0;
309            break;
310        }
311        BE_STREAM_TO_UINT8(num_vals, p);
312        p_result->get_app_val_txt.num_attr = num_vals;
313        AVRC_TRACE_DEBUG("%s value count = %d ", __func__, p_result->get_app_val_txt.num_attr);
314
315        p_setting_text = (tAVRC_APP_SETTING_TEXT *)osi_malloc(num_vals * sizeof(tAVRC_APP_SETTING_TEXT));
316        for (int i = 0; i < num_vals; i++) {
317            BE_STREAM_TO_UINT8(p_result->get_app_val_txt.p_attrs[i].attr_id, p);
318            BE_STREAM_TO_UINT16(p_result->get_app_val_txt.p_attrs[i].charset_id, p);
319            BE_STREAM_TO_UINT8(p_result->get_app_val_txt.p_attrs[i].str_len, p);
320            if (p_result->get_app_val_txt.p_attrs[i].str_len != 0) {
321                UINT8 *p_str = (UINT8 *)osi_malloc(p_result->get_app_val_txt.p_attrs[i].str_len);
322                BE_STREAM_TO_ARRAY(p, p_str, p_result->get_app_val_txt.p_attrs[i].str_len);
323                p_result->get_app_val_txt.p_attrs[i].p_str = p_str;
324            } else {
325                p_result->get_app_val_txt.p_attrs[i].p_str = NULL;
326            }
327        }
328    }
329        break;
330
331    case AVRC_PDU_SET_PLAYER_APP_VALUE:
332        /* nothing comes as part of this rsp */
333        break;
334
335    case AVRC_PDU_GET_ELEMENT_ATTR:
336    {
337        UINT8               num_attrs;
338
339        if (len <= 0)
340        {
341            p_result->get_elem_attrs.num_attr = 0;
342            break;
343        }
344        BE_STREAM_TO_UINT8(num_attrs, p);
345        p_result->get_elem_attrs.num_attr = num_attrs;
346        if (num_attrs)
347        {
348            tAVRC_ATTR_ENTRY *p_attrs =
349                (tAVRC_ATTR_ENTRY*)osi_malloc(num_attrs * sizeof(tAVRC_ATTR_ENTRY));
350            for (int i = 0; i < num_attrs; i++) {
351                BE_STREAM_TO_UINT32(p_attrs[i].attr_id, p);
352                BE_STREAM_TO_UINT16(p_attrs[i].name.charset_id, p);
353                BE_STREAM_TO_UINT16(p_attrs[i].name.str_len, p);
354                if (p_attrs[i].name.str_len > 0) {
355                    p_attrs[i].name.p_str = (UINT8 *)osi_malloc(p_attrs[i].name.str_len);
356                    BE_STREAM_TO_ARRAY(p, p_attrs[i].name.p_str, p_attrs[i].name.str_len);
357                }
358            }
359            p_result->get_elem_attrs.p_attrs = p_attrs;
360        }
361    }
362        break;
363
364    case AVRC_PDU_GET_PLAY_STATUS:
365        if (len == 0)
366        {
367            break;
368        }
369        BE_STREAM_TO_UINT32(p_result->get_play_status.song_len, p);
370        BE_STREAM_TO_UINT32(p_result->get_play_status.song_pos, p);
371        BE_STREAM_TO_UINT8(p_result->get_play_status.status, p);
372        break;
373
374    default:
375        return AVRC_STS_BAD_CMD;
376    }
377    return AVRC_STS_NO_ERROR;
378}
379
380/*******************************************************************************
381**
382** Function         AVRC_Ctrl_ParsResponse
383**
384** Description      This function is a parse response for AVRCP Controller.
385**
386** Returns          AVRC_STS_NO_ERROR, if the message in p_data is parsed successfully.
387**                  Otherwise, the error code defined by AVRCP 1.4
388**
389*******************************************************************************/
390tAVRC_STS AVRC_Ctrl_ParsResponse (tAVRC_MSG *p_msg, tAVRC_RESPONSE *p_result, UINT8 *p_buf, UINT16* buf_len)
391{
392    tAVRC_STS  status = AVRC_STS_INTERNAL_ERR;
393    if (p_msg && p_result)
394    {
395        switch (p_msg->hdr.opcode)
396        {
397        case AVRC_OP_VENDOR:     /*  0x00    Vendor-dependent commands */
398            status = avrc_ctrl_pars_vendor_rsp(&p_msg->vendor, p_result, p_buf,buf_len);
399            break;
400
401        default:
402            AVRC_TRACE_ERROR("%s unknown opcode:0x%x", __func__, p_msg->hdr.opcode);
403            break;
404        }
405        p_result->rsp.opcode = p_msg->hdr.opcode;
406        p_result->rsp.status = status;
407    }
408    return status;
409}
410#endif /* (AVRC_CTRL_INCLUDED) == TRUE) */
411/*******************************************************************************
412**
413** Function         AVRC_ParsResponse
414**
415** Description      This function is a superset of AVRC_ParsMetadata to parse the response.
416**
417** Returns          AVRC_STS_NO_ERROR, if the message in p_data is parsed successfully.
418**                  Otherwise, the error code defined by AVRCP 1.4
419**
420*******************************************************************************/
421tAVRC_STS AVRC_ParsResponse (tAVRC_MSG *p_msg, tAVRC_RESPONSE *p_result, UINT8 *p_buf, UINT16 buf_len)
422{
423    tAVRC_STS  status = AVRC_STS_INTERNAL_ERR;
424    UINT16  id;
425    UNUSED(p_buf);
426    UNUSED(buf_len);
427
428    if (p_msg && p_result)
429    {
430        switch (p_msg->hdr.opcode)
431        {
432        case AVRC_OP_VENDOR:     /*  0x00    Vendor-dependent commands */
433            status = avrc_pars_vendor_rsp(&p_msg->vendor, p_result);
434            break;
435
436        case AVRC_OP_PASS_THRU:  /*  0x7C    panel subunit opcode */
437            status = avrc_pars_pass_thru(&p_msg->pass, &id);
438            if (status == AVRC_STS_NO_ERROR)
439            {
440                p_result->pdu = (UINT8)id;
441            }
442            break;
443
444        default:
445            AVRC_TRACE_ERROR("%s unknown opcode:0x%x", __func__, p_msg->hdr.opcode);
446            break;
447        }
448        p_result->rsp.opcode = p_msg->hdr.opcode;
449        p_result->rsp.status = status;
450    }
451    return status;
452}
453#endif /* (AVRC_METADATA_INCLUDED == TRUE) */
454