OSDN Git Service

am 83970699: (-s ours) am 8d502374: commit 001ccea74ec61b1be00c8ede827f55c0359d1051...
[android-x86/system-bt.git] / stack / avrc / avrc_pars_tg.c
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_pars_vendor_cmd
33 **
34 ** Description      This function parses the vendor specific commands defined by
35 **                  Bluetooth SIG
36 **
37 ** Returns          AVRC_STS_NO_ERROR, if the message in p_data is parsed successfully.
38 **                  Otherwise, the error code defined by AVRCP 1.4
39 **
40 *******************************************************************************/
41 static tAVRC_STS avrc_pars_vendor_cmd(tAVRC_MSG_VENDOR *p_msg, tAVRC_COMMAND *p_result,
42                                       UINT8 *p_buf, UINT16 buf_len)
43 {
44     tAVRC_STS  status = AVRC_STS_NO_ERROR;
45     UINT8   *p = p_msg->p_vendor_data;
46     UINT16  len;
47     UINT8   xx, yy;
48     UINT8   *p_u8;
49     UINT16  *p_u16;
50     UINT32  u32, u32_2, *p_u32;
51     tAVRC_APP_SETTING       *p_app_set;
52     UINT16  size_needed;
53
54     p_result->pdu = *p++;
55     AVRC_TRACE_DEBUG("avrc_pars_vendor_cmd() pdu:0x%x", p_result->pdu);
56     if (!AVRC_IsValidAvcType (p_result->pdu, p_msg->hdr.ctype))
57     {
58         AVRC_TRACE_DEBUG("avrc_pars_vendor_cmd() detects wrong AV/C type!");
59         status = AVRC_STS_BAD_CMD;
60     }
61
62     p++; /* skip the reserved byte */
63     BE_STREAM_TO_UINT16 (len, p);
64     if ((len+4) != (p_msg->vendor_len))
65     {
66         status = AVRC_STS_INTERNAL_ERR;
67     }
68
69     if (status != AVRC_STS_NO_ERROR)
70         return status;
71
72     switch (p_result->pdu)
73     {
74     case AVRC_PDU_GET_CAPABILITIES:         /* 0x10 */
75         p_result->get_caps.capability_id = *p++;
76         if (!AVRC_IS_VALID_CAP_ID(p_result->get_caps.capability_id))
77             status = AVRC_STS_BAD_PARAM;
78         else if (len != 1)
79             status = AVRC_STS_INTERNAL_ERR;
80         break;
81
82     case AVRC_PDU_LIST_PLAYER_APP_ATTR:     /* 0x11 */
83         /* no additional parameters */
84         if (len != 0)
85             status = AVRC_STS_INTERNAL_ERR;
86         break;
87
88     case AVRC_PDU_LIST_PLAYER_APP_VALUES:   /* 0x12 */
89         p_result->list_app_values.attr_id = *p++;
90         if (!AVRC_IS_VALID_ATTRIBUTE(p_result->list_app_values.attr_id))
91             status = AVRC_STS_BAD_PARAM;
92         else if (len != 1)
93             status = AVRC_STS_INTERNAL_ERR;
94         break;
95
96     case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE: /* 0x13 */
97     case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT: /* 0x15 */
98         BE_STREAM_TO_UINT8 (p_result->get_cur_app_val.num_attr, p);
99         if (len != (p_result->get_cur_app_val.num_attr+1))
100         {
101             status = AVRC_STS_INTERNAL_ERR;
102             break;
103         }
104         p_u8 = p_result->get_cur_app_val.attrs;
105         for (xx=0, yy=0; xx< p_result->get_cur_app_val.num_attr; xx++)
106         {
107             /* only report the valid player app attributes */
108             if (AVRC_IsValidPlayerAttr(*p))
109                 p_u8[yy++] = *p;
110             p++;
111         }
112         p_result->get_cur_app_val.num_attr = yy;
113         if (yy == 0)
114         {
115             status = AVRC_STS_BAD_PARAM;
116         }
117         break;
118
119     case AVRC_PDU_SET_PLAYER_APP_VALUE:     /* 0x14 */
120         BE_STREAM_TO_UINT8 (p_result->set_app_val.num_val, p);
121         size_needed = sizeof(tAVRC_APP_SETTING);
122         if (p_buf && (len == ((p_result->set_app_val.num_val<<1) + 1)))
123         {
124             p_result->set_app_val.p_vals = (tAVRC_APP_SETTING *)p_buf;
125             p_app_set = p_result->set_app_val.p_vals;
126             for (xx=0; ((xx< p_result->set_app_val.num_val) && (buf_len > size_needed)); xx++)
127             {
128                 p_app_set[xx].attr_id = *p++;
129                 p_app_set[xx].attr_val = *p++;
130                 if (!avrc_is_valid_player_attrib_value(p_app_set[xx].attr_id, p_app_set[xx].attr_val))
131                     status = AVRC_STS_BAD_PARAM;
132             }
133             if (xx != p_result->set_app_val.num_val)
134             {
135                 AVRC_TRACE_ERROR("AVRC_PDU_SET_PLAYER_APP_VALUE not enough room:%d orig num_val:%d",
136                     xx, p_result->set_app_val.num_val);
137                 p_result->set_app_val.num_val = xx;
138             }
139         }
140         else
141         {
142             AVRC_TRACE_ERROR("AVRC_PDU_SET_PLAYER_APP_VALUE NULL decode buffer or bad len");
143             status = AVRC_STS_INTERNAL_ERR;
144         }
145         break;
146
147     case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT:/* 0x16 */
148         if (len < 3)
149             status = AVRC_STS_INTERNAL_ERR;
150         else
151         {
152             BE_STREAM_TO_UINT8 (p_result->get_app_val_txt.attr_id, p);
153             if (!AVRC_IS_VALID_ATTRIBUTE(p_result->get_app_val_txt.attr_id))
154                 status = AVRC_STS_BAD_PARAM;
155             else
156             {
157                 BE_STREAM_TO_UINT8 (p_result->get_app_val_txt.num_val, p);
158                 if ( (len - 2/* attr_id & num_val */) != p_result->get_app_val_txt.num_val)
159                     status = AVRC_STS_INTERNAL_ERR;
160                 else
161                 {
162                     p_u8 = p_result->get_app_val_txt.vals;
163                     for (xx=0; xx< p_result->get_app_val_txt.num_val; xx++)
164                     {
165                         p_u8[xx] = *p++;
166                         if (!avrc_is_valid_player_attrib_value(p_result->get_app_val_txt.attr_id,
167                             p_u8[xx]))
168                         {
169                             status = AVRC_STS_BAD_PARAM;
170                             break;
171                         }
172                     }
173                 }
174             }
175         }
176         break;
177
178     case AVRC_PDU_INFORM_DISPLAY_CHARSET:  /* 0x17 */
179         if (len < 3)
180             status = AVRC_STS_INTERNAL_ERR;
181         else
182         {
183             BE_STREAM_TO_UINT8 (p_result->inform_charset.num_id, p);
184             if ( (len - 1/* num_id */) != p_result->inform_charset.num_id * 2)
185                 status = AVRC_STS_INTERNAL_ERR;
186             else
187             {
188                 p_u16 = p_result->inform_charset.charsets;
189                 if (p_result->inform_charset.num_id > AVRC_MAX_CHARSET_SIZE)
190                     p_result->inform_charset.num_id = AVRC_MAX_CHARSET_SIZE;
191                 for (xx=0; xx< p_result->inform_charset.num_id; xx++)
192                 {
193                     BE_STREAM_TO_UINT16 (p_u16[xx], p);
194                 }
195             }
196         }
197         break;
198
199     case AVRC_PDU_INFORM_BATTERY_STAT_OF_CT:/* 0x18 */
200         if (len != 1)
201             status = AVRC_STS_INTERNAL_ERR;
202         else
203         {
204             p_result->inform_battery_status.battery_status = *p++;
205             if (!AVRC_IS_VALID_BATTERY_STATUS(p_result->inform_battery_status.battery_status))
206                 status = AVRC_STS_BAD_PARAM;
207         }
208         break;
209
210     case AVRC_PDU_GET_ELEMENT_ATTR:         /* 0x20 */
211         if (len < 9) /* UID/8 and num_attr/1 */
212             status = AVRC_STS_INTERNAL_ERR;
213         else
214         {
215             BE_STREAM_TO_UINT32 (u32, p);
216             BE_STREAM_TO_UINT32 (u32_2, p);
217             if (u32== 0 && u32_2 == 0)
218             {
219                 BE_STREAM_TO_UINT8 (p_result->get_elem_attrs.num_attr, p);
220                 if ( (len - 9/* UID/8 and num_attr/1 */) != (p_result->get_elem_attrs.num_attr * 4))
221                     status = AVRC_STS_INTERNAL_ERR;
222                 else
223                 {
224                     p_u32 = p_result->get_elem_attrs.attrs;
225                     if (p_result->get_elem_attrs.num_attr > AVRC_MAX_ELEM_ATTR_SIZE)
226                         p_result->get_elem_attrs.num_attr = AVRC_MAX_ELEM_ATTR_SIZE;
227                     for (xx=0; xx< p_result->get_elem_attrs.num_attr; xx++)
228                     {
229                         BE_STREAM_TO_UINT32 (p_u32[xx], p);
230                     }
231                 }
232             }
233             else
234                 status = AVRC_STS_NOT_FOUND;
235         }
236         break;
237
238     case AVRC_PDU_GET_PLAY_STATUS:          /* 0x30 */
239         /* no additional parameters */
240         if (len != 0)
241             status = AVRC_STS_INTERNAL_ERR;
242         break;
243
244     case AVRC_PDU_REGISTER_NOTIFICATION:    /* 0x31 */
245         if (len != 5)
246             status = AVRC_STS_INTERNAL_ERR;
247         else
248         {
249             BE_STREAM_TO_UINT8 (p_result->reg_notif.event_id, p);
250             BE_STREAM_TO_UINT32 (p_result->reg_notif.param, p);
251         }
252         break;
253
254     case AVRC_PDU_SET_ABSOLUTE_VOLUME:
255     {
256         if(len!=1)
257             status = AVRC_STS_INTERNAL_ERR;
258         break;
259     }
260
261     /* case AVRC_PDU_REQUEST_CONTINUATION_RSP: 0x40 */
262     /* case AVRC_PDU_ABORT_CONTINUATION_RSP:   0x41 */
263
264     default:
265         status = AVRC_STS_BAD_CMD;
266         break;
267     }
268
269     return status;
270 }
271
272 /*******************************************************************************
273 **
274 ** Function         AVRC_ParsCommand
275 **
276 ** Description      This function is a superset of AVRC_ParsMetadata to parse the command.
277 **
278 ** Returns          AVRC_STS_NO_ERROR, if the message in p_data is parsed successfully.
279 **                  Otherwise, the error code defined by AVRCP 1.4
280 **
281 *******************************************************************************/
282 tAVRC_STS AVRC_ParsCommand (tAVRC_MSG *p_msg, tAVRC_COMMAND *p_result, UINT8 *p_buf, UINT16 buf_len)
283 {
284     tAVRC_STS  status = AVRC_STS_INTERNAL_ERR;
285     UINT16  id;
286
287     if (p_msg && p_result)
288     {
289         switch (p_msg->hdr.opcode)
290         {
291         case AVRC_OP_VENDOR:     /*  0x00    Vendor-dependent commands */
292             status = avrc_pars_vendor_cmd(&p_msg->vendor, p_result, p_buf, buf_len);
293             break;
294
295         case AVRC_OP_PASS_THRU:  /*  0x7C    panel subunit opcode */
296             status = avrc_pars_pass_thru(&p_msg->pass, &id);
297             if (status == AVRC_STS_NO_ERROR)
298             {
299                 p_result->pdu = (UINT8)id;
300             }
301             break;
302
303         default:
304             AVRC_TRACE_ERROR("AVRC_ParsCommand() unknown opcode:0x%x", p_msg->hdr.opcode);
305             break;
306         }
307         p_result->cmd.opcode = p_msg->hdr.opcode;
308         p_result->cmd.status = status;
309     }
310     AVRC_TRACE_DEBUG("AVRC_ParsCommand() return status:0x%x", status);
311     return status;
312 }
313
314 #endif /* (AVRC_METADATA_INCLUDED == TRUE) */
315