• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 *******************************************************************************/
avrc_pars_vendor_rsp(tAVRC_MSG_VENDOR * p_msg,tAVRC_RESPONSE * p_result)43 static 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 
avrc_parse_notification_rsp(UINT8 * p_stream,tAVRC_REG_NOTIF_RSP * p_rsp)109 void 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 *******************************************************************************/
avrc_ctrl_pars_vendor_rsp(tAVRC_MSG_VENDOR * p_msg,tAVRC_RESPONSE * p_result,UINT8 * p_buf,UINT16 * buf_len)165 static 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 *******************************************************************************/
AVRC_Ctrl_ParsResponse(tAVRC_MSG * p_msg,tAVRC_RESPONSE * p_result,UINT8 * p_buf,UINT16 * buf_len)390 tAVRC_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 *******************************************************************************/
AVRC_ParsResponse(tAVRC_MSG * p_msg,tAVRC_RESPONSE * p_result,UINT8 * p_buf,UINT16 buf_len)421 tAVRC_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