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