1 /******************************************************************************
2  *
3  *  Copyright (C) 2002-2012 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 
19 /******************************************************************************
20  *
21  *  This module contains functions for parsing and building AVDTP signaling
22  *  messages.  It also contains functions called by the SCB or CCB state
23  *  machines for sending command, response, and reject messages.  It also
24  *  contains a function that processes incoming messages and dispatches them
25  *  to the appropriate SCB or CCB.
26  *
27  ******************************************************************************/
28 
29 #include <string.h>
30 #include "stack/bt_types.h"
31 #include "common/bt_target.h"
32 #include "common/bt_defs.h"
33 #include "stack/avdt_api.h"
34 #include "stack/avdtc_api.h"
35 #include "avdt_int.h"
36 #include "stack/btu.h"
37 #include "osi/allocator.h"
38 
39 #if (defined(AVDT_INCLUDED) && AVDT_INCLUDED == TRUE)
40 /*****************************************************************************
41 ** constants
42 *****************************************************************************/
43 
44 /* mask of all psc values */
45 #define AVDT_MSG_PSC_MASK   (AVDT_PSC_TRANS | AVDT_PSC_REPORT | AVDT_PSC_DELAY_RPT | \
46                              AVDT_PSC_RECOV | AVDT_PSC_HDRCMP | AVDT_PSC_MUX)
47 #define AVDT_PSC_PROTECT    (1<<4)  /* Content Protection */
48 #define AVDT_PSC_CODEC      (1<<7)  /* codec */
49 
50 
51 /*****************************************************************************
52 ** type definitions
53 *****************************************************************************/
54 
55 /* type for message building functions */
56 typedef void (*tAVDT_MSG_BLD)(UINT8 **p, tAVDT_MSG *p_msg);
57 
58 /* type for message parsing functions */
59 typedef UINT8 (*tAVDT_MSG_PRS)(tAVDT_MSG *p_msg, UINT8 *p, UINT16 len);
60 
61 
62 /*****************************************************************************
63 ** local function declarations
64 *****************************************************************************/
65 
66 static void avdt_msg_bld_none(UINT8 **p, tAVDT_MSG *p_msg);
67 static void avdt_msg_bld_single(UINT8 **p, tAVDT_MSG *p_msg);
68 static void avdt_msg_bld_setconfig_cmd(UINT8 **p, tAVDT_MSG *p_msg);
69 static void avdt_msg_bld_reconfig_cmd(UINT8 **p, tAVDT_MSG *p_msg);
70 static void avdt_msg_bld_multi(UINT8 **p, tAVDT_MSG *p_msg);
71 static void avdt_msg_bld_security_cmd(UINT8 **p, tAVDT_MSG *p_msg);
72 static void avdt_msg_bld_discover_rsp(UINT8 **p, tAVDT_MSG *p_msg);
73 static void avdt_msg_bld_svccap(UINT8 **p, tAVDT_MSG *p_msg);
74 static void avdt_msg_bld_security_rsp(UINT8 **p, tAVDT_MSG *p_msg);
75 static void avdt_msg_bld_all_svccap(UINT8 **p, tAVDT_MSG *p_msg);
76 static void avdt_msg_bld_delay_rpt(UINT8 **p, tAVDT_MSG *p_msg);
77 
78 static UINT8 avdt_msg_prs_none(tAVDT_MSG *p_msg, UINT8 *p, UINT16 len);
79 static UINT8 avdt_msg_prs_single(tAVDT_MSG *p_msg, UINT8 *p, UINT16 len);
80 static UINT8 avdt_msg_prs_setconfig_cmd(tAVDT_MSG *p_msg, UINT8 *p, UINT16 len);
81 static UINT8 avdt_msg_prs_reconfig_cmd(tAVDT_MSG *p_msg, UINT8 *p, UINT16 len);
82 static UINT8 avdt_msg_prs_multi(tAVDT_MSG *p_msg, UINT8 *p, UINT16 len);
83 static UINT8 avdt_msg_prs_security_cmd(tAVDT_MSG *p_msg, UINT8 *p, UINT16 len);
84 static UINT8 avdt_msg_prs_discover_rsp(tAVDT_MSG *p_msg, UINT8 *p, UINT16 len);
85 static UINT8 avdt_msg_prs_svccap(tAVDT_MSG *p_msg, UINT8 *p, UINT16 len);
86 static UINT8 avdt_msg_prs_all_svccap(tAVDT_MSG *p_msg, UINT8 *p, UINT16 len);
87 static UINT8 avdt_msg_prs_security_rsp(tAVDT_MSG *p_msg, UINT8 *p, UINT16 len);
88 static UINT8 avdt_msg_prs_delay_rpt (tAVDT_MSG *p_msg, UINT8 *p, UINT16 len);
89 
90 /*****************************************************************************
91 ** constants
92 *****************************************************************************/
93 
94 /* table of information element minimum lengths used for parsing */
95 const UINT8 avdt_msg_ie_len_min[] = {
96     0,                              /* unused */
97     AVDT_LEN_TRANS_MIN,             /* media transport */
98     AVDT_LEN_REPORT_MIN,            /* reporting */
99     AVDT_LEN_RECOV_MIN,             /* recovery */
100     AVDT_LEN_PROTECT_MIN,           /* content protection */
101     AVDT_LEN_HDRCMP_MIN,            /* header compression */
102     AVDT_LEN_MUX_MIN,               /* multiplexing */
103     AVDT_LEN_CODEC_MIN,             /* codec */
104     AVDT_LEN_DELAY_RPT_MIN          /* delay report */
105 };
106 
107 /* table of information element minimum lengths used for parsing */
108 const UINT8 avdt_msg_ie_len_max[] = {
109     0,                              /* unused */
110     AVDT_LEN_TRANS_MAX,             /* media transport */
111     AVDT_LEN_REPORT_MAX,            /* reporting */
112     AVDT_LEN_RECOV_MAX,             /* recovery */
113     AVDT_LEN_PROTECT_MAX,           /* content protection */
114     AVDT_LEN_HDRCMP_MAX,            /* header compression */
115     AVDT_LEN_MUX_MAX,               /* multiplexing */
116     AVDT_LEN_CODEC_MAX,             /* codec */
117     AVDT_LEN_DELAY_RPT_MAX          /* delay report */
118 };
119 
120 /* table of error codes used when decoding information elements */
121 const UINT8 avdt_msg_ie_err[] = {
122     0,                              /* unused */
123     AVDT_ERR_MEDIA_TRANS,           /* media transport */
124     AVDT_ERR_LENGTH,                /* reporting */
125     AVDT_ERR_RECOV_FMT,             /* recovery */
126     AVDT_ERR_CP_FMT,                /* content protection */
127     AVDT_ERR_ROHC_FMT,              /* header compression */
128     AVDT_ERR_MUX_FMT,               /* multiplexing */
129     AVDT_ERR_SERVICE,               /* codec */
130     AVDT_ERR_SERVICE                /* delay report ?? */
131 };
132 
133 /* table of packet type minimum lengths */
134 static const UINT8 avdt_msg_pkt_type_len[] = {
135     AVDT_LEN_TYPE_SINGLE,
136     AVDT_LEN_TYPE_START,
137     AVDT_LEN_TYPE_CONT,
138     AVDT_LEN_TYPE_END
139 };
140 
141 /* function table for building command messages */
142 const tAVDT_MSG_BLD avdt_msg_bld_cmd[] = {
143     avdt_msg_bld_none,            /* discover */
144     avdt_msg_bld_single,          /* get capabilities */
145     avdt_msg_bld_setconfig_cmd,   /* set configuration */
146     avdt_msg_bld_single,          /* get configuration */
147     avdt_msg_bld_reconfig_cmd,    /* reconfigure */
148     avdt_msg_bld_single,          /* open */
149     avdt_msg_bld_multi,           /* start */
150     avdt_msg_bld_single,          /* close */
151     avdt_msg_bld_multi,           /* suspend */
152     avdt_msg_bld_single,          /* abort */
153     avdt_msg_bld_security_cmd,    /* security control */
154     avdt_msg_bld_single,          /* get all capabilities */
155     avdt_msg_bld_delay_rpt        /* delay report */
156 };
157 
158 /* function table for building response messages */
159 const tAVDT_MSG_BLD avdt_msg_bld_rsp[] = {
160     avdt_msg_bld_discover_rsp,    /* discover */
161     avdt_msg_bld_svccap,          /* get capabilities */
162     avdt_msg_bld_none,            /* set configuration */
163     avdt_msg_bld_all_svccap,      /* get configuration */
164     avdt_msg_bld_none,            /* reconfigure */
165     avdt_msg_bld_none,            /* open */
166     avdt_msg_bld_none,            /* start */
167     avdt_msg_bld_none,            /* close */
168     avdt_msg_bld_none,            /* suspend */
169     avdt_msg_bld_none,            /* abort */
170     avdt_msg_bld_security_rsp,    /* security control */
171     avdt_msg_bld_all_svccap,      /* get all capabilities */
172     avdt_msg_bld_none             /* delay report */
173 };
174 
175 /* function table for parsing command messages */
176 const tAVDT_MSG_PRS avdt_msg_prs_cmd[] = {
177     avdt_msg_prs_none,            /* discover */
178     avdt_msg_prs_single,          /* get capabilities */
179     avdt_msg_prs_setconfig_cmd,   /* set configuration */
180     avdt_msg_prs_single,          /* get configuration */
181     avdt_msg_prs_reconfig_cmd,    /* reconfigure */
182     avdt_msg_prs_single,          /* open */
183     avdt_msg_prs_multi,           /* start */
184     avdt_msg_prs_single,          /* close */
185     avdt_msg_prs_multi,           /* suspend */
186     avdt_msg_prs_single,          /* abort */
187     avdt_msg_prs_security_cmd,    /* security control */
188     avdt_msg_prs_single,          /* get all capabilities */
189     avdt_msg_prs_delay_rpt        /* delay report */
190 };
191 
192 /* function table for parsing response messages */
193 const tAVDT_MSG_PRS avdt_msg_prs_rsp[] = {
194     avdt_msg_prs_discover_rsp,    /* discover */
195     avdt_msg_prs_svccap,          /* get capabilities */
196     avdt_msg_prs_none,            /* set configuration */
197     avdt_msg_prs_all_svccap,      /* get configuration */
198     avdt_msg_prs_none,            /* reconfigure */
199     avdt_msg_prs_none,            /* open */
200     avdt_msg_prs_none,            /* start */
201     avdt_msg_prs_none,            /* close */
202     avdt_msg_prs_none,            /* suspend */
203     avdt_msg_prs_none,            /* abort */
204     avdt_msg_prs_security_rsp,    /* security control */
205     avdt_msg_prs_all_svccap,      /* get all capabilities */
206     avdt_msg_prs_none             /* delay report */
207 };
208 
209 /* command message-to-event lookup table */
210 const UINT8 avdt_msg_cmd_2_evt[] = {
211     AVDT_CCB_MSG_DISCOVER_CMD_EVT + AVDT_CCB_MKR,   /* discover */
212     AVDT_CCB_MSG_GETCAP_CMD_EVT + AVDT_CCB_MKR,     /* get capabilities */
213     AVDT_SCB_MSG_SETCONFIG_CMD_EVT,                 /* set configuration */
214     AVDT_SCB_MSG_GETCONFIG_CMD_EVT,                 /* get configuration */
215     AVDT_SCB_MSG_RECONFIG_CMD_EVT,                  /* reconfigure */
216     AVDT_SCB_MSG_OPEN_CMD_EVT,                      /* open */
217     AVDT_CCB_MSG_START_CMD_EVT + AVDT_CCB_MKR,      /* start */
218     AVDT_SCB_MSG_CLOSE_CMD_EVT,                     /* close */
219     AVDT_CCB_MSG_SUSPEND_CMD_EVT + AVDT_CCB_MKR,    /* suspend */
220     AVDT_SCB_MSG_ABORT_CMD_EVT,                     /* abort */
221     AVDT_SCB_MSG_SECURITY_CMD_EVT,                  /* security control */
222     AVDT_CCB_MSG_GETCAP_CMD_EVT + AVDT_CCB_MKR,     /* get all capabilities */
223     AVDT_SCB_MSG_DELAY_RPT_CMD_EVT                  /* delay report */
224 };
225 
226 /* response message-to-event lookup table */
227 const UINT8 avdt_msg_rsp_2_evt[] = {
228     AVDT_CCB_MSG_DISCOVER_RSP_EVT + AVDT_CCB_MKR,   /* discover */
229     AVDT_CCB_MSG_GETCAP_RSP_EVT + AVDT_CCB_MKR,     /* get capabilities */
230     AVDT_SCB_MSG_SETCONFIG_RSP_EVT,                 /* set configuration */
231     AVDT_SCB_MSG_GETCONFIG_RSP_EVT,                 /* get configuration */
232     AVDT_SCB_MSG_RECONFIG_RSP_EVT,                  /* reconfigure */
233     AVDT_SCB_MSG_OPEN_RSP_EVT,                      /* open */
234     AVDT_CCB_MSG_START_RSP_EVT + AVDT_CCB_MKR,      /* start */
235     AVDT_SCB_MSG_CLOSE_RSP_EVT,                     /* close */
236     AVDT_CCB_MSG_SUSPEND_RSP_EVT + AVDT_CCB_MKR,    /* suspend */
237     AVDT_SCB_MSG_ABORT_RSP_EVT,                     /* abort */
238     AVDT_SCB_MSG_SECURITY_RSP_EVT,                  /* security control */
239     AVDT_CCB_MSG_GETCAP_RSP_EVT + AVDT_CCB_MKR,     /* get all capabilities */
240     AVDT_SCB_MSG_DELAY_RPT_RSP_EVT                  /* delay report */
241 };
242 
243 /* reject message-to-event lookup table */
244 const UINT8 avdt_msg_rej_2_evt[] = {
245     AVDT_CCB_MSG_DISCOVER_RSP_EVT + AVDT_CCB_MKR,   /* discover */
246     AVDT_CCB_MSG_GETCAP_RSP_EVT + AVDT_CCB_MKR,     /* get capabilities */
247     AVDT_SCB_MSG_SETCONFIG_REJ_EVT,                 /* set configuration */
248     AVDT_SCB_MSG_GETCONFIG_RSP_EVT,                 /* get configuration */
249     AVDT_SCB_MSG_RECONFIG_RSP_EVT,                  /* reconfigure */
250     AVDT_SCB_MSG_OPEN_REJ_EVT,                      /* open */
251     AVDT_CCB_MSG_START_RSP_EVT + AVDT_CCB_MKR,      /* start */
252     AVDT_SCB_MSG_CLOSE_RSP_EVT,                     /* close */
253     AVDT_CCB_MSG_SUSPEND_RSP_EVT + AVDT_CCB_MKR,    /* suspend */
254     AVDT_SCB_MSG_ABORT_RSP_EVT,                     /* abort */
255     AVDT_SCB_MSG_SECURITY_RSP_EVT,                  /* security control */
256     AVDT_CCB_MSG_GETCAP_RSP_EVT + AVDT_CCB_MKR,     /* get all capabilities */
257     0                                               /* delay report */
258 };
259 
260 /*******************************************************************************
261 **
262 ** Function         avdt_msg_bld_cfg
263 **
264 ** Description      This function builds the configuration parameters contained
265 **                  in a command or response message.
266 **
267 **
268 ** Returns          void.
269 **
270 *******************************************************************************/
avdt_msg_bld_cfg(UINT8 ** p,tAVDT_CFG * p_cfg)271 static void avdt_msg_bld_cfg(UINT8 **p, tAVDT_CFG *p_cfg)
272 {
273     UINT8 len;
274 
275     /* for now, just build media transport, codec, and content protection, and multiplexing */
276 
277     /* media transport */
278     if (p_cfg->psc_mask & AVDT_PSC_TRANS) {
279         *(*p)++ = AVDT_CAT_TRANS;
280         *(*p)++ = 0; /* length */
281     }
282 
283 #if AVDT_REPORTING == TRUE
284     /* reporting transport */
285     if (p_cfg->psc_mask & AVDT_PSC_REPORT) {
286         *(*p)++ = AVDT_CAT_REPORT;
287         *(*p)++ = 0; /* length */
288     }
289 #endif
290 
291     /* codec */
292     if (p_cfg->num_codec != 0) {
293         *(*p)++ = AVDT_CAT_CODEC;
294         len = p_cfg->codec_info[0] + 1;
295         if ( len > AVDT_CODEC_SIZE ) {
296             len = AVDT_CODEC_SIZE;
297         }
298 
299         memcpy(*p, p_cfg->codec_info, len);
300         *p += len;
301     }
302 
303     /* content protection */
304     if (p_cfg->num_protect != 0) {
305         *(*p)++ = AVDT_CAT_PROTECT;
306         len = p_cfg->protect_info[0] + 1;
307         if ( len > AVDT_PROTECT_SIZE ) {
308             len = AVDT_PROTECT_SIZE;
309         }
310 
311         memcpy(*p, p_cfg->protect_info, len);
312         *p += len;
313     }
314 
315 #if AVDT_MULTIPLEXING == TRUE
316     /* multiplexing */
317     if (p_cfg->psc_mask & AVDT_PSC_MUX) {
318         *(*p)++ = AVDT_CAT_MUX;
319         /* length */
320         if (p_cfg->psc_mask & AVDT_PSC_RECOV) {
321             *(*p)++ = 7;    /* frag (1) + media + report + recovery */
322         } else if (p_cfg->psc_mask & AVDT_PSC_REPORT) {
323             *(*p)++ = 5;    /* frag (1) + media + report */
324         } else {
325             *(*p)++ = 3;    /* frag (1) + media */
326         }
327 
328         /* allow fragmentation */
329         if (p_cfg->mux_mask & AVDT_MUX_FRAG) {
330             *(*p)++ = 0x80;
331         } else {
332             *(*p)++ = 0;
333         }
334 
335         /* media transport session */
336         *(*p)++ = p_cfg->mux_tsid_media << 3; /* TSID */
337         *(*p)++ = p_cfg->mux_tcid_media << 3; /* TCID */
338 
339         if (p_cfg->psc_mask & AVDT_PSC_RECOV) {
340             /* reporting transport session */
341             *(*p)++ = p_cfg->mux_tsid_report << 3; /* TSID */
342             *(*p)++ = p_cfg->mux_tcid_report << 3; /* TCID */
343             /* recovery transport session */
344             *(*p)++ = p_cfg->mux_tsid_recov << 3; /* TSID */
345             *(*p)++ = p_cfg->mux_tcid_recov << 3; /* TCID */
346         } else if (p_cfg->psc_mask & AVDT_PSC_REPORT) {
347             /* reporting transport session */
348             *(*p)++ = p_cfg->mux_tsid_report << 3; /* TSID */
349             *(*p)++ = p_cfg->mux_tcid_report << 3; /* TCID */
350         }
351     }
352 #endif
353 
354     /* delay report */
355     if (p_cfg->psc_mask & AVDT_PSC_DELAY_RPT) {
356         *(*p)++ = AVDT_CAT_DELAY_RPT;
357         *(*p)++ = 0; /* length */
358     }
359 }
360 
361 /*******************************************************************************
362 **
363 ** Function         avdt_msg_bld_none
364 **
365 ** Description      This message building function builds an empty message.
366 **
367 **
368 ** Returns          void.
369 **
370 *******************************************************************************/
avdt_msg_bld_none(UINT8 ** p,tAVDT_MSG * p_msg)371 static void avdt_msg_bld_none(UINT8 **p, tAVDT_MSG *p_msg)
372 {
373     UNUSED(p);
374     UNUSED(p_msg);
375     return;
376 }
377 
378 /*******************************************************************************
379 **
380 ** Function         avdt_msg_bld_single
381 **
382 ** Description      This message building function builds a message containing
383 **                  a single SEID.
384 **
385 **
386 ** Returns          void.
387 **
388 *******************************************************************************/
avdt_msg_bld_single(UINT8 ** p,tAVDT_MSG * p_msg)389 static void avdt_msg_bld_single(UINT8 **p, tAVDT_MSG *p_msg)
390 {
391     AVDT_MSG_BLD_SEID(*p, p_msg->single.seid);
392 }
393 
394 /*******************************************************************************
395 **
396 ** Function         avdt_msg_bld_setconfig_cmd
397 **
398 ** Description      This message building function builds a set configuration
399 **                  command message.
400 **
401 **
402 ** Returns          void.
403 **
404 *******************************************************************************/
avdt_msg_bld_setconfig_cmd(UINT8 ** p,tAVDT_MSG * p_msg)405 static void avdt_msg_bld_setconfig_cmd(UINT8 **p, tAVDT_MSG *p_msg)
406 {
407     AVDT_MSG_BLD_SEID(*p, p_msg->config_cmd.hdr.seid);
408     AVDT_MSG_BLD_SEID(*p, p_msg->config_cmd.int_seid);
409     avdt_msg_bld_cfg(p, p_msg->config_cmd.p_cfg);
410 }
411 
412 /*******************************************************************************
413 **
414 ** Function         avdt_msg_bld_reconfig_cmd
415 **
416 ** Description      This message building function builds a reconfiguration
417 **                  command message.
418 **
419 **
420 ** Returns          void.
421 **
422 *******************************************************************************/
avdt_msg_bld_reconfig_cmd(UINT8 ** p,tAVDT_MSG * p_msg)423 static void avdt_msg_bld_reconfig_cmd(UINT8 **p, tAVDT_MSG *p_msg)
424 {
425     AVDT_MSG_BLD_SEID(*p, p_msg->reconfig_cmd.hdr.seid);
426 
427     /* force psc mask zero to build only codec and security */
428     p_msg->reconfig_cmd.p_cfg->psc_mask = 0;
429     avdt_msg_bld_cfg(p, p_msg->reconfig_cmd.p_cfg);
430 }
431 
432 /*******************************************************************************
433 **
434 ** Function         avdt_msg_bld_multi
435 **
436 ** Description      This message building function builds a message containing
437 **                  multiple SEID's.
438 **
439 **
440 ** Returns          void.
441 **
442 *******************************************************************************/
avdt_msg_bld_multi(UINT8 ** p,tAVDT_MSG * p_msg)443 static void avdt_msg_bld_multi(UINT8 **p, tAVDT_MSG *p_msg)
444 {
445     int i;
446 
447     for (i = 0; i < p_msg->multi.num_seps; i++) {
448         AVDT_MSG_BLD_SEID(*p, p_msg->multi.seid_list[i]);
449     }
450 }
451 
452 /*******************************************************************************
453 **
454 ** Function         avdt_msg_bld_security_cmd
455 **
456 ** Description      This message building function builds a security
457 **                  command message.
458 **
459 ** Returns          void.
460 **
461 *******************************************************************************/
avdt_msg_bld_security_cmd(UINT8 ** p,tAVDT_MSG * p_msg)462 static void avdt_msg_bld_security_cmd(UINT8 **p, tAVDT_MSG *p_msg)
463 {
464     AVDT_MSG_BLD_SEID(*p, p_msg->security_cmd.hdr.seid);
465     memcpy(*p, p_msg->security_cmd.p_data, p_msg->security_cmd.len);
466     *p += p_msg->security_cmd.len;
467 }
468 
469 /*******************************************************************************
470 **
471 ** Function         avdt_msg_bld_delay_rpt
472 **
473 ** Description      This message building function builds a delay report
474 **                  command message.
475 **
476 ** Returns          void.
477 **
478 *******************************************************************************/
avdt_msg_bld_delay_rpt(UINT8 ** p,tAVDT_MSG * p_msg)479 static void avdt_msg_bld_delay_rpt(UINT8 **p, tAVDT_MSG *p_msg)
480 {
481     AVDT_MSG_BLD_SEID(*p, p_msg->delay_rpt_cmd.hdr.seid);
482     UINT16_TO_BE_STREAM(*p, p_msg->delay_rpt_cmd.delay);
483 }
484 
485 /*******************************************************************************
486 **
487 ** Function         avdt_msg_bld_discover_rsp
488 **
489 ** Description      This message building function builds a discover
490 **                  response message.
491 **
492 **
493 ** Returns          void.
494 **
495 *******************************************************************************/
avdt_msg_bld_discover_rsp(UINT8 ** p,tAVDT_MSG * p_msg)496 static void avdt_msg_bld_discover_rsp(UINT8 **p, tAVDT_MSG *p_msg)
497 {
498     int     i;
499 
500     for (i = 0; i < p_msg->discover_rsp.num_seps; i++) {
501         /* build discover rsp info */
502         AVDT_MSG_BLD_DISC(*p, p_msg->discover_rsp.p_sep_info[i].seid,
503                           p_msg->discover_rsp.p_sep_info[i].in_use,
504                           p_msg->discover_rsp.p_sep_info[i].media_type,
505                           p_msg->discover_rsp.p_sep_info[i].tsep);
506     }
507 }
508 
509 /*******************************************************************************
510 **
511 ** Function         avdt_msg_bld_svccap
512 **
513 ** Description      This message building function builds a message containing
514 **                  service capabilities parameters.
515 **
516 **
517 ** Returns          void.
518 **
519 *******************************************************************************/
avdt_msg_bld_svccap(UINT8 ** p,tAVDT_MSG * p_msg)520 static void avdt_msg_bld_svccap(UINT8 **p, tAVDT_MSG *p_msg)
521 {
522     tAVDT_CFG cfg;
523 
524     /* make sure the delay report category is not reported */
525     memcpy (&cfg, p_msg->svccap.p_cfg, sizeof(tAVDT_CFG));
526     cfg.psc_mask &= ~AVDT_PSC_DELAY_RPT;
527     avdt_msg_bld_cfg(p, &cfg);
528 }
529 
530 /*******************************************************************************
531 **
532 ** Function         avdt_msg_bld_all_svccap
533 **
534 ** Description      This message building function builds a message containing
535 **                  service capabilities parameters.
536 **
537 **
538 ** Returns          void.
539 **
540 *******************************************************************************/
avdt_msg_bld_all_svccap(UINT8 ** p,tAVDT_MSG * p_msg)541 static void avdt_msg_bld_all_svccap(UINT8 **p, tAVDT_MSG *p_msg)
542 {
543     avdt_msg_bld_cfg(p, p_msg->svccap.p_cfg);
544 }
545 
546 /*******************************************************************************
547 **
548 ** Function         avdt_msg_bld_security_rsp
549 **
550 ** Description      This message building function builds a security
551 **                  response message.
552 **
553 **
554 ** Returns          void.
555 **
556 *******************************************************************************/
avdt_msg_bld_security_rsp(UINT8 ** p,tAVDT_MSG * p_msg)557 static void avdt_msg_bld_security_rsp(UINT8 **p, tAVDT_MSG *p_msg)
558 {
559     memcpy(*p, p_msg->security_rsp.p_data, p_msg->security_rsp.len);
560     *p += p_msg->security_rsp.len;
561 }
562 
563 /*******************************************************************************
564 **
565 ** Function         avdt_msg_prs_cfg
566 **
567 ** Description      This message parsing function parses the configuration
568 **                  parameters field of a message.
569 **
570 **
571 ** Returns          Error code or zero if no error, and element that failed
572 **                  in p_elem.
573 **
574 *******************************************************************************/
avdt_msg_prs_cfg(tAVDT_CFG * p_cfg,UINT8 * p,UINT16 len,UINT8 * p_elem,UINT8 sig_id)575 static UINT8 avdt_msg_prs_cfg(tAVDT_CFG *p_cfg, UINT8 *p, UINT16 len, UINT8 *p_elem, UINT8 sig_id)
576 {
577     UINT8   *p_end;
578     UINT8   elem = 0;
579     UINT8   elem_len;
580     UINT8   tmp;
581     UINT8   err = 0;
582     UINT8   protect_offset = 0;
583 
584     if (!p_cfg) {
585         AVDT_TRACE_ERROR ("not expecting this cfg");
586         return AVDT_ERR_BAD_STATE;
587     }
588 
589     p_cfg->psc_mask = 0;
590     p_cfg->num_codec = 0;
591     p_cfg->num_protect = 0;
592 #if AVDT_MULTIPLEXING == TRUE
593     p_cfg->mux_mask = 0;
594 #endif
595 
596     /* while there is still data to parse */
597     p_end = p + len;
598     while ((p < p_end) && (err == 0)) {
599         /* verify overall length */
600         if ((p_end - p) < AVDT_LEN_CFG_MIN) {
601             err = AVDT_ERR_PAYLOAD;
602             break;
603         }
604 
605         /* get and verify info elem id, length */
606         elem = *p++;
607         elem_len = *p++;
608 
609         if ((elem == 0) || (elem > AVDT_CAT_MAX_CUR)) {
610             /* this may not be really bad.
611              * It may be a service category that is too new for us.
612              * allow these to be parsed without reporting an error.
613              * If this is a "capability" (as in GetCapRsp & GetConfigRsp), this is filtered out.
614              * If this is a Configuration (as in SetConfigCmd & ReconfigCmd),
615              *    this will be marked as an error in the caller of this function */
616             if ((sig_id == AVDT_SIG_SETCONFIG) || (sig_id == AVDT_SIG_RECONFIG)) {
617                 /* Cannot accept unknown category. */
618                 err = AVDT_ERR_CATEGORY;
619                 break;
620             } else { /* GETCAP or GET_ALLCAP */
621                 /* Skip unknown categories. */
622                 p += elem_len;
623                 AVDT_TRACE_DEBUG("skipping unknown service category=%d len: %d\n", elem, elem_len);
624                 continue;
625             }
626         }
627 
628         if ((elem_len > avdt_msg_ie_len_max[elem]) ||
629                 (elem_len < avdt_msg_ie_len_min[elem])) {
630             err = avdt_msg_ie_err[elem];
631             break;
632         }
633 
634         /* add element to psc mask, but mask out codec or protect */
635         p_cfg->psc_mask |= (1 << elem);
636         AVDT_TRACE_DEBUG("elem=%d elem_len: %d psc_mask=0x%x\n", elem, elem_len, p_cfg->psc_mask);
637 
638         /* parse individual information elements with additional parameters */
639         switch (elem) {
640         case AVDT_CAT_RECOV:
641             p_cfg->recov_type = *p++;
642             p_cfg->recov_mrws = *p++;
643             p_cfg->recov_mnmp = *p++;
644             if (p_cfg->recov_type != AVDT_RECOV_RFC2733) {
645                 err = AVDT_ERR_RECOV_TYPE;
646             } else if ((p_cfg->recov_mrws < AVDT_RECOV_MRWS_MIN) ||
647                        (p_cfg->recov_mrws > AVDT_RECOV_MRWS_MAX) ||
648                        (p_cfg->recov_mnmp < AVDT_RECOV_MNMP_MIN) ||
649                        (p_cfg->recov_mnmp > AVDT_RECOV_MNMP_MAX)) {
650                 err = AVDT_ERR_RECOV_FMT;
651             }
652             break;
653 
654         case AVDT_CAT_PROTECT:
655             p_cfg->psc_mask &= ~AVDT_PSC_PROTECT;
656             if ((elem_len + protect_offset) < AVDT_PROTECT_SIZE) {
657                 p_cfg->num_protect++;
658                 p_cfg->protect_info[protect_offset] = elem_len;
659                 protect_offset++;
660                 memcpy(&p_cfg->protect_info[protect_offset], p, elem_len);
661                 protect_offset += elem_len;
662             }
663             p += elem_len;
664             break;
665 
666         case AVDT_CAT_HDRCMP:
667             p_cfg->hdrcmp_mask = *p++;
668             break;
669 
670 #if AVDT_MULTIPLEXING == TRUE
671         case AVDT_CAT_MUX:
672             /* verify length */
673             AVDT_TRACE_WARNING("psc_mask=0x%x elem_len=%d\n", p_cfg->psc_mask, elem_len);
674             if ( ((0 == (p_cfg->psc_mask & (AVDT_PSC_RECOV | AVDT_PSC_REPORT))) && (elem_len != 3))
675                     || (((p_cfg->psc_mask & AVDT_PSC_REPORT) && !(p_cfg->psc_mask & AVDT_PSC_RECOV))
676                         && (elem_len != 5))
677                     || ((!(p_cfg->psc_mask & AVDT_PSC_REPORT) && (p_cfg->psc_mask & AVDT_PSC_RECOV))
678                         && (elem_len != 5))
679                     || (((p_cfg->psc_mask & AVDT_PSC_REPORT) && (p_cfg->psc_mask & AVDT_PSC_RECOV))
680                         && (elem_len != 7)) ) {
681                 err = AVDT_ERR_MUX_FMT;
682                 break;
683             }
684 
685             /* parse fragmentation */
686             p_cfg->mux_mask = *p++ & (UINT8)AVDT_MUX_FRAG;
687 
688             /* parse TSIDs and TCIDs */
689             if (--elem_len) {
690                 p_cfg->mux_tsid_media = (*p++) >> 3;
691             } else {
692                 break;
693             }
694 
695             if (--elem_len) {
696                 p_cfg->mux_tcid_media = (*p++) >> 3;
697             } else {
698                 break;
699             }
700 
701             if (--elem_len) {
702                 p_cfg->mux_tsid_report = (*p++) >> 3;
703             } else {
704                 break;
705             }
706 
707             if (--elem_len) {
708                 p_cfg->mux_tcid_report = (*p++) >> 3;
709             } else {
710                 break;
711             }
712 
713             if (--elem_len) {
714                 p_cfg->mux_tsid_recov = (*p++) >> 3;
715             } else {
716                 break;
717             }
718 
719             if (--elem_len) {
720                 p_cfg->mux_tcid_recov = (*p++) >> 3;
721             } else {
722                 break;
723             }
724             break;
725 #endif
726 
727         case AVDT_CAT_CODEC:
728             p_cfg->psc_mask &= ~AVDT_PSC_CODEC;
729             tmp = elem_len;
730             if (elem_len >= AVDT_CODEC_SIZE) {
731                 tmp = AVDT_CODEC_SIZE - 1;
732             }
733             p_cfg->num_codec++;
734             p_cfg->codec_info[0] = elem_len;
735             memcpy(&p_cfg->codec_info[1], p, tmp);
736             p += elem_len;
737             break;
738 
739         case AVDT_CAT_DELAY_RPT:
740             break;
741 
742         default:
743             p += elem_len;
744             break;
745         } /* switch */
746     } /* while ! err, !end*/
747     *p_elem = elem;
748     AVDT_TRACE_DEBUG("err=0x%x, elem:0x%x psc_mask=0x%x\n", err, elem, p_cfg->psc_mask);
749 
750     return err;
751 }
752 
753 /*******************************************************************************
754 **
755 ** Function         avdt_msg_prs_none
756 **
757 ** Description      This message parsing function parses a message with no parameters.
758 
759 **
760 **
761 ** Returns          Error code or zero if no error.
762 **
763 *******************************************************************************/
avdt_msg_prs_none(tAVDT_MSG * p_msg,UINT8 * p,UINT16 len)764 static UINT8 avdt_msg_prs_none(tAVDT_MSG *p_msg, UINT8 *p, UINT16 len)
765 {
766     UNUSED(p_msg);
767     UNUSED(p);
768     UNUSED(len);
769     return 0;
770 }
771 
772 /*******************************************************************************
773 **
774 ** Function         avdt_msg_prs_single
775 **
776 ** Description      This message parsing function parses a message with a
777 **                  single SEID.
778 **
779 **
780 ** Returns          Error code or zero if no error.
781 **
782 *******************************************************************************/
avdt_msg_prs_single(tAVDT_MSG * p_msg,UINT8 * p,UINT16 len)783 static UINT8 avdt_msg_prs_single(tAVDT_MSG *p_msg, UINT8 *p, UINT16 len)
784 {
785     UINT8       err = 0;
786 
787     /* verify len */
788     if (len != AVDT_LEN_SINGLE) {
789         err = AVDT_ERR_LENGTH;
790     } else {
791         AVDT_MSG_PRS_SEID(p, p_msg->single.seid);
792 
793         if (avdt_scb_by_hdl(p_msg->single.seid) == NULL) {
794             err = AVDT_ERR_SEID;
795         }
796     }
797     return err;
798 }
799 
800 /*******************************************************************************
801 **
802 ** Function         avdt_msg_prs_setconfig_cmd
803 **
804 ** Description      This message parsing function parses a set configuration
805 **                  command message.
806 **
807 **
808 ** Returns          Error code or zero if no error.
809 **
810 *******************************************************************************/
avdt_msg_prs_setconfig_cmd(tAVDT_MSG * p_msg,UINT8 * p,UINT16 len)811 static UINT8 avdt_msg_prs_setconfig_cmd(tAVDT_MSG *p_msg, UINT8 *p, UINT16 len)
812 {
813     UINT8       err = 0;
814 
815     p_msg->hdr.err_param = 0;
816 
817     /* verify len */
818     if (len < AVDT_LEN_SETCONFIG_MIN) {
819         err = AVDT_ERR_LENGTH;
820     } else {
821         /* get seids */
822         AVDT_MSG_PRS_SEID(p, p_msg->config_cmd.hdr.seid);
823         if (avdt_scb_by_hdl(p_msg->config_cmd.hdr.seid) == NULL) {
824             err = AVDT_ERR_SEID;
825         }
826 
827         AVDT_MSG_PRS_SEID(p, p_msg->config_cmd.int_seid);
828         if ((p_msg->config_cmd.int_seid < AVDT_SEID_MIN) ||
829                 (p_msg->config_cmd.int_seid > AVDT_SEID_MAX)) {
830             err = AVDT_ERR_SEID;
831         }
832     }
833 
834     if (!err) {
835         /* parse configuration parameters */
836         len -= 2;
837         err = avdt_msg_prs_cfg(p_msg->config_cmd.p_cfg, p, len, &p_msg->hdr.err_param, AVDT_SIG_SETCONFIG);
838 
839         if (!err) {
840             /* verify protocol service capabilities are supported */
841             if (((p_msg->config_cmd.p_cfg->psc_mask & (~AVDT_PSC)) != 0) ||
842                     (p_msg->config_cmd.p_cfg->num_codec == 0)) {
843                 err = AVDT_ERR_INVALID_CAP;
844             }
845         }
846     }
847 
848     return err;
849 }
850 
851 /*******************************************************************************
852 **
853 ** Function         avdt_msg_prs_reconfig_cmd
854 **
855 ** Description      This message parsing function parses a reconfiguration
856 **                  command message.
857 **
858 **
859 ** Returns          Error code or zero if no error.
860 **
861 *******************************************************************************/
avdt_msg_prs_reconfig_cmd(tAVDT_MSG * p_msg,UINT8 * p,UINT16 len)862 static UINT8 avdt_msg_prs_reconfig_cmd(tAVDT_MSG *p_msg, UINT8 *p, UINT16 len)
863 {
864     UINT8       err = 0;
865 
866     p_msg->hdr.err_param = 0;
867 
868     /* verify len */
869     if (len < AVDT_LEN_RECONFIG_MIN) {
870         err = AVDT_ERR_LENGTH;
871     } else {
872         /* get seid */
873         AVDT_MSG_PRS_SEID(p, p_msg->reconfig_cmd.hdr.seid);
874         if (avdt_scb_by_hdl(p_msg->reconfig_cmd.hdr.seid) == NULL) {
875             err = AVDT_ERR_SEID;
876         } else {
877             /* parse config parameters */
878             len--;
879             err = avdt_msg_prs_cfg(p_msg->config_cmd.p_cfg, p, len, &p_msg->hdr.err_param, AVDT_SIG_RECONFIG);
880 
881             /* verify no protocol service capabilities in parameters */
882             if (!err) {
883                 AVDT_TRACE_DEBUG("avdt_msg_prs_reconfig_cmd psc_mask=0x%x/0x%x\n", p_msg->config_cmd.p_cfg->psc_mask, AVDT_MSG_PSC_MASK);
884                 if ((p_msg->config_cmd.p_cfg->psc_mask != 0) ||
885                         (p_msg->config_cmd.p_cfg->num_codec == 0 && p_msg->config_cmd.p_cfg->num_protect == 0)) {
886                     err = AVDT_ERR_INVALID_CAP;
887                 }
888             }
889         }
890     }
891     return err;
892 }
893 
894 /*******************************************************************************
895 **
896 ** Function         avdt_msg_prs_multi
897 **
898 ** Description      This message parsing function parses a message containing
899 **                  multiple SEID's.
900 **
901 **
902 ** Returns          Error code or zero if no error.
903 **
904 *******************************************************************************/
avdt_msg_prs_multi(tAVDT_MSG * p_msg,UINT8 * p,UINT16 len)905 static UINT8 avdt_msg_prs_multi(tAVDT_MSG *p_msg, UINT8 *p, UINT16 len)
906 {
907     int     i;
908     UINT8   err = 0;
909 
910     p_msg->hdr.err_param = 0;
911 
912     /* verify len */
913     if (len < AVDT_LEN_MULTI_MIN || (len > AVDT_NUM_SEPS)) {
914         err = AVDT_ERR_LENGTH;
915     } else {
916         /* get and verify all seps */
917         for (i = 0; i < len; i++) {
918             AVDT_MSG_PRS_SEID(p, p_msg->multi.seid_list[i]);
919             if (avdt_scb_by_hdl(p_msg->multi.seid_list[i]) == NULL) {
920                 err = AVDT_ERR_SEID;
921                 p_msg->hdr.err_param = p_msg->multi.seid_list[i];
922                 break;
923             }
924         }
925         p_msg->multi.num_seps = (UINT8)i;
926     }
927 
928     return err;
929 }
930 
931 /*******************************************************************************
932 **
933 ** Function         avdt_msg_prs_security_cmd
934 **
935 ** Description      This message parsing function parses a security
936 **                  command message.
937 **
938 **
939 ** Returns          Error code or zero if no error.
940 **
941 *******************************************************************************/
avdt_msg_prs_security_cmd(tAVDT_MSG * p_msg,UINT8 * p,UINT16 len)942 static UINT8 avdt_msg_prs_security_cmd(tAVDT_MSG *p_msg, UINT8 *p, UINT16 len)
943 {
944     UINT8       err = 0;
945 
946     /* verify len */
947     if (len < AVDT_LEN_SECURITY_MIN) {
948         err = AVDT_ERR_LENGTH;
949     } else {
950         /* get seid */
951         AVDT_MSG_PRS_SEID(p, p_msg->security_cmd.hdr.seid);
952         if (avdt_scb_by_hdl(p_msg->security_cmd.hdr.seid) == NULL) {
953             err = AVDT_ERR_SEID;
954         } else {
955             p_msg->security_cmd.p_data = p;
956             p_msg->security_cmd.len = len - 1;
957         }
958     }
959     return err;
960 }
961 
962 /*******************************************************************************
963 **
964 ** Function         avdt_msg_prs_discover_rsp
965 **
966 ** Description      This message parsing function parses a discover
967 **                  response message.
968 **
969 **
970 ** Returns          Error code or zero if no error.
971 **
972 *******************************************************************************/
avdt_msg_prs_discover_rsp(tAVDT_MSG * p_msg,UINT8 * p,UINT16 len)973 static UINT8 avdt_msg_prs_discover_rsp(tAVDT_MSG *p_msg, UINT8 *p, UINT16 len)
974 {
975     int     i;
976     UINT8   err = 0;
977 
978     /* determine number of seps; seps in msg is len/2, but set to minimum
979     ** of seps app has supplied memory for and seps in msg
980     */
981     if (p_msg->discover_rsp.num_seps > (len / 2)) {
982         p_msg->discover_rsp.num_seps = (len / 2);
983     }
984 
985     /* parse out sep info */
986     for (i = 0; i < p_msg->discover_rsp.num_seps; i++) {
987         /* parse discover rsp info */
988         AVDT_MSG_PRS_DISC(p, p_msg->discover_rsp.p_sep_info[i].seid,
989                           p_msg->discover_rsp.p_sep_info[i].in_use,
990                           p_msg->discover_rsp.p_sep_info[i].media_type,
991                           p_msg->discover_rsp.p_sep_info[i].tsep);
992 
993         /* verify that seid is valid */
994         if ((p_msg->discover_rsp.p_sep_info[i].seid < AVDT_SEID_MIN) ||
995                 (p_msg->discover_rsp.p_sep_info[i].seid > AVDT_SEID_MAX)) {
996             err = AVDT_ERR_SEID;
997             break;
998         }
999     }
1000 
1001     return err;
1002 }
1003 
1004 /*******************************************************************************
1005 **
1006 ** Function         avdt_msg_prs_svccap
1007 **
1008 ** Description      This message parsing function parses a message containing
1009 **                  service capabilities parameters.
1010 **
1011 **
1012 ** Returns          Error code or zero if no error.
1013 **
1014 *******************************************************************************/
avdt_msg_prs_svccap(tAVDT_MSG * p_msg,UINT8 * p,UINT16 len)1015 static UINT8 avdt_msg_prs_svccap(tAVDT_MSG *p_msg, UINT8 *p, UINT16 len)
1016 {
1017     /* parse parameters */
1018     UINT8   err = avdt_msg_prs_cfg(p_msg->svccap.p_cfg, p, len, &p_msg->hdr.err_param, AVDT_SIG_GETCAP);
1019     if (p_msg->svccap.p_cfg) {
1020         p_msg->svccap.p_cfg->psc_mask &= AVDT_LEG_PSC;
1021     }
1022 
1023     return (err);
1024 }
1025 
1026 /*******************************************************************************
1027 **
1028 ** Function         avdt_msg_prs_all_svccap
1029 **
1030 ** Description      This message parsing function parses a message containing
1031 **                  service capabilities parameters.
1032 **
1033 **
1034 ** Returns          Error code or zero if no error.
1035 **
1036 *******************************************************************************/
avdt_msg_prs_all_svccap(tAVDT_MSG * p_msg,UINT8 * p,UINT16 len)1037 static UINT8 avdt_msg_prs_all_svccap(tAVDT_MSG *p_msg, UINT8 *p, UINT16 len)
1038 {
1039     UINT8   err = avdt_msg_prs_cfg(p_msg->svccap.p_cfg, p, len, &p_msg->hdr.err_param, AVDT_SIG_GET_ALLCAP);
1040     if (p_msg->svccap.p_cfg) {
1041         p_msg->svccap.p_cfg->psc_mask &= AVDT_MSG_PSC_MASK;
1042     }
1043     return (err);
1044 }
1045 
1046 /*******************************************************************************
1047 **
1048 ** Function         avdt_msg_prs_security_rsp
1049 **
1050 ** Description      This message parsing function parsing a security
1051 **                  response message.
1052 **
1053 **
1054 ** Returns          Error code or zero if no error.
1055 **
1056 *******************************************************************************/
avdt_msg_prs_security_rsp(tAVDT_MSG * p_msg,UINT8 * p,UINT16 len)1057 static UINT8 avdt_msg_prs_security_rsp(tAVDT_MSG *p_msg, UINT8 *p, UINT16 len)
1058 {
1059     p_msg->security_rsp.p_data = p;
1060     p_msg->security_rsp.len = len;
1061 
1062     return 0;
1063 }
1064 
1065 /*******************************************************************************
1066 **
1067 ** Function         avdt_msg_prs_rej
1068 **
1069 ** Description
1070 **
1071 **
1072 ** Returns          Error code or zero if no error.
1073 **
1074 *******************************************************************************/
avdt_msg_prs_rej(tAVDT_MSG * p_msg,UINT8 * p,UINT8 sig)1075 static UINT8 avdt_msg_prs_rej(tAVDT_MSG *p_msg, UINT8 *p, UINT8 sig)
1076 {
1077     if ((sig == AVDT_SIG_SETCONFIG) || (sig == AVDT_SIG_RECONFIG)) {
1078         p_msg->hdr.err_param = *p++;
1079         p_msg->hdr.err_code = *p;
1080     } else if ((sig == AVDT_SIG_START) || (sig == AVDT_SIG_SUSPEND)) {
1081         AVDT_MSG_PRS_SEID(p, p_msg->hdr.err_param);
1082         p_msg->hdr.err_code = *p;
1083     } else {
1084         p_msg->hdr.err_code = *p;
1085     }
1086 
1087     return 0;
1088 }
1089 
1090 /*******************************************************************************
1091 **
1092 ** Function         avdt_msg_prs_delay_rpt
1093 **
1094 ** Description      This message parsing function parses a security
1095 **                  command message.
1096 **
1097 **
1098 ** Returns          Error code or zero if no error.
1099 **
1100 *******************************************************************************/
avdt_msg_prs_delay_rpt(tAVDT_MSG * p_msg,UINT8 * p,UINT16 len)1101 static UINT8 avdt_msg_prs_delay_rpt (tAVDT_MSG *p_msg, UINT8 *p, UINT16 len)
1102 {
1103     UINT8       err = 0;
1104 
1105     /* verify len */
1106     if (len != AVDT_LEN_DELAY_RPT) {
1107         AVDT_TRACE_WARNING("avdt_msg_prs_delay_rpt expected len: %u  got: %u\n", AVDT_LEN_DELAY_RPT, len);
1108         err = AVDT_ERR_LENGTH;
1109     } else {
1110         /* get seid */
1111         AVDT_MSG_PRS_SEID (p, p_msg->delay_rpt_cmd.hdr.seid);
1112 
1113         if (avdt_scb_by_hdl(p_msg->delay_rpt_cmd.hdr.seid) == NULL) {
1114             err = AVDT_ERR_SEID;
1115         } else {
1116             BE_STREAM_TO_UINT16 (p_msg->delay_rpt_cmd.delay, p);
1117             AVDT_TRACE_DEBUG("avdt_msg_prs_delay_rpt delay: %u\n", p_msg->delay_rpt_cmd.delay);
1118         }
1119     }
1120     return err;
1121 }
1122 
1123 
1124 /*******************************************************************************
1125 **
1126 ** Function         avdt_msg_send
1127 **
1128 ** Description      Send, and if necessary fragment the next message.
1129 **
1130 **
1131 ** Returns          Congested state; TRUE if CCB congested, FALSE if not.
1132 **
1133 *******************************************************************************/
avdt_msg_send(tAVDT_CCB * p_ccb,BT_HDR * p_msg)1134 BOOLEAN avdt_msg_send(tAVDT_CCB *p_ccb, BT_HDR *p_msg)
1135 {
1136     UINT16          curr_msg_len;
1137     UINT8           pkt_type;
1138     UINT8           hdr_len;
1139     tAVDT_TC_TBL    *p_tbl;
1140     BT_HDR          *p_buf;
1141     UINT8           *p;
1142     UINT8           label;
1143     UINT8           msg;
1144     UINT8           sig;
1145     UINT8           nosp = 0;       /* number of subsequent packets */
1146 
1147     /* look up transport channel table entry to get peer mtu */
1148     p_tbl = avdt_ad_tc_tbl_by_type(AVDT_CHAN_SIG, p_ccb, NULL);
1149 
1150     /* set the current message if there is a message passed in */
1151     if (p_msg != NULL) {
1152         p_ccb->p_curr_msg = p_msg;
1153     }
1154 
1155     /* store copy of curr_msg->len */
1156     curr_msg_len = p_ccb->p_curr_msg->len;
1157 
1158     /* while not congested and we haven't sent it all */
1159     while ((!p_ccb->cong) && (p_ccb->p_curr_msg != NULL)) {
1160         /* check what kind of message we've got here; we are using the offset
1161         ** to indicate that a message is being fragmented
1162         */
1163 
1164         /* if message isn't being fragmented and it fits in mtu */
1165         if ((p_ccb->p_curr_msg->offset == AVDT_MSG_OFFSET) &&
1166                 (p_ccb->p_curr_msg->len <= p_tbl->peer_mtu - AVDT_LEN_TYPE_SINGLE)) {
1167             pkt_type = AVDT_PKT_TYPE_SINGLE;
1168             hdr_len = AVDT_LEN_TYPE_SINGLE;
1169             p_buf = p_ccb->p_curr_msg;
1170         }
1171         /* if message isn't being fragmented and it doesn't fit in mtu */
1172         else if ((p_ccb->p_curr_msg->offset == AVDT_MSG_OFFSET) &&
1173                  (p_ccb->p_curr_msg->len > p_tbl->peer_mtu - AVDT_LEN_TYPE_SINGLE)) {
1174             pkt_type = AVDT_PKT_TYPE_START;
1175             hdr_len = AVDT_LEN_TYPE_START;
1176             nosp = (p_ccb->p_curr_msg->len + AVDT_LEN_TYPE_START - p_tbl->peer_mtu) /
1177                    (p_tbl->peer_mtu - 1) + 2;
1178 
1179             /* get a new buffer for fragment we are sending */
1180             if ((p_buf = (BT_HDR *) osi_malloc(AVDT_CMD_BUF_SIZE)) == NULL) {
1181                 /* do we even want to try and recover from this? could do so
1182                 by setting retransmission timer */
1183                 return TRUE;
1184             }
1185 
1186             /* copy portion of data from current message to new buffer */
1187             p_buf->offset = L2CAP_MIN_OFFSET + hdr_len;
1188             p_buf->len = p_tbl->peer_mtu - hdr_len;
1189             memcpy((UINT8 *)(p_buf + 1) + p_buf->offset,
1190                    (UINT8 *)(p_ccb->p_curr_msg + 1) + p_ccb->p_curr_msg->offset, p_buf->len);
1191         }
1192         /* if message is being fragmented and remaining bytes don't fit in mtu */
1193         else if ((p_ccb->p_curr_msg->offset > AVDT_MSG_OFFSET) &&
1194                  (p_ccb->p_curr_msg->len > (p_tbl->peer_mtu - AVDT_LEN_TYPE_CONT))) {
1195             pkt_type = AVDT_PKT_TYPE_CONT;
1196             hdr_len = AVDT_LEN_TYPE_CONT;
1197 
1198             /* get a new buffer for fragment we are sending */
1199             if ((p_buf = (BT_HDR *) osi_malloc(AVDT_CMD_BUF_SIZE)) == NULL) {
1200                 /* do we even want to try and recover from this? could do so
1201                 by setting retransmission timer */
1202                 return TRUE;
1203             }
1204 
1205             /* copy portion of data from current message to new buffer */
1206             p_buf->offset = L2CAP_MIN_OFFSET + hdr_len;
1207             p_buf->len = p_tbl->peer_mtu - hdr_len;
1208             memcpy((UINT8 *)(p_buf + 1) + p_buf->offset,
1209                    (UINT8 *)(p_ccb->p_curr_msg + 1) + p_ccb->p_curr_msg->offset, p_buf->len);
1210         }
1211         /* if message is being fragmented and remaining bytes do fit in mtu */
1212         else {
1213             pkt_type = AVDT_PKT_TYPE_END;
1214             hdr_len = AVDT_LEN_TYPE_END;
1215             p_buf = p_ccb->p_curr_msg;
1216         }
1217 
1218         /* label, sig id, msg type are in hdr of p_curr_msg */
1219         label = AVDT_LAYERSPEC_LABEL(p_ccb->p_curr_msg->layer_specific);
1220         msg = AVDT_LAYERSPEC_MSG(p_ccb->p_curr_msg->layer_specific);
1221         sig = (UINT8) p_ccb->p_curr_msg->event;
1222         AVDT_TRACE_DEBUG("avdt_msg_send label:%d, msg:%d, sig:%d\n", label, msg, sig);
1223 
1224         /* keep track of how much of msg we've sent */
1225         curr_msg_len -= p_buf->len;
1226         if (curr_msg_len == 0) {
1227             /* entire message sent; mark as finished */
1228             p_ccb->p_curr_msg = NULL;
1229 
1230             /* start timer here for commands */
1231             if (msg == AVDT_MSG_TYPE_CMD) {
1232                 /* if retransmit timeout set to zero, sig doesn't use retransmit */
1233                 if ((sig == AVDT_SIG_DISCOVER) || (sig == AVDT_SIG_GETCAP) ||
1234                         (sig == AVDT_SIG_SECURITY) || (avdt_cb.rcb.ret_tout == 0)) {
1235                     btu_start_timer(&p_ccb->timer_entry, BTU_TTYPE_AVDT_CCB_RSP, avdt_cb.rcb.sig_tout);
1236                 } else if (sig != AVDT_SIG_DELAY_RPT) {
1237                     btu_start_timer(&p_ccb->timer_entry, BTU_TTYPE_AVDT_CCB_RET, avdt_cb.rcb.ret_tout);
1238                 }
1239             }
1240         } else {
1241             /* message being fragmented and not completely sent */
1242             p_ccb->p_curr_msg->len -= p_buf->len;
1243             p_ccb->p_curr_msg->offset += p_buf->len;
1244         }
1245 
1246         /* set up to build header */
1247         p_buf->len += hdr_len;
1248         p_buf->offset -= hdr_len;
1249         p = (UINT8 *)(p_buf + 1) + p_buf->offset;
1250 
1251         /* build header */
1252         AVDT_MSG_BLD_HDR(p, label, pkt_type, msg);
1253         if (pkt_type == AVDT_PKT_TYPE_START) {
1254             AVDT_MSG_BLD_NOSP(p, nosp);
1255         }
1256         if ((pkt_type == AVDT_PKT_TYPE_START) || (pkt_type == AVDT_PKT_TYPE_SINGLE)) {
1257             AVDT_MSG_BLD_SIG(p, sig);
1258         }
1259 
1260         /* send msg buffer down */
1261         avdt_ad_write_req(AVDT_CHAN_SIG, p_ccb, NULL, p_buf);
1262     }
1263     return (p_ccb->cong);
1264 }
1265 
1266 /*******************************************************************************
1267 **
1268 ** Function         avdt_msg_asmbl
1269 **
1270 ** Description      Reassemble incoming message.
1271 **
1272 **
1273 ** Returns          Pointer to reassembled message;  NULL if no message
1274 **                  available.
1275 **
1276 *******************************************************************************/
avdt_msg_asmbl(tAVDT_CCB * p_ccb,BT_HDR * p_buf)1277 BT_HDR *avdt_msg_asmbl(tAVDT_CCB *p_ccb, BT_HDR *p_buf)
1278 {
1279     UINT8   *p;
1280     UINT8   pkt_type;
1281     BT_HDR  *p_ret;
1282     UINT16  buf_len;
1283 
1284     /* parse the message header */
1285     p = (UINT8 *)(p_buf + 1) + p_buf->offset;
1286     AVDT_MSG_PRS_PKT_TYPE(p, pkt_type);
1287 
1288     /* quick sanity check on length */
1289     if (p_buf->len < avdt_msg_pkt_type_len[pkt_type]) {
1290         osi_free(p_buf);
1291         AVDT_TRACE_WARNING("Bad length during reassembly");
1292         p_ret = NULL;
1293     }
1294     /* single packet */
1295     else if (pkt_type == AVDT_PKT_TYPE_SINGLE) {
1296         /* if reassembly in progress drop message and process new single */
1297         if (p_ccb->p_rx_msg != NULL) {
1298             osi_free(p_ccb->p_rx_msg);
1299             p_ccb->p_rx_msg = NULL;
1300             AVDT_TRACE_WARNING("Got single during reassembly");
1301         }
1302         p_ret = p_buf;
1303     }
1304     /* start packet */
1305     else if (pkt_type == AVDT_PKT_TYPE_START) {
1306         /* if reassembly in progress drop message and process new single */
1307         if (p_ccb->p_rx_msg != NULL) {
1308 		    osi_free(p_ccb->p_rx_msg);
1309 		    p_ccb->p_rx_msg = NULL;
1310             AVDT_TRACE_WARNING("Got start during reassembly");
1311         }
1312         /*
1313          * Allocate bigger buffer for reassembly. As lower layers are
1314          * not aware of possible packet size after reassembly, they
1315          * would have allocated smaller buffer.
1316          */
1317         p_ccb->p_rx_msg = (BT_HDR *)osi_malloc(BT_DEFAULT_BUFFER_SIZE);
1318         memcpy(p_ccb->p_rx_msg, p_buf,
1319                sizeof(BT_HDR) + p_buf->offset + p_buf->len);
1320 
1321         /* Free original buffer */
1322         osi_free(p_buf);
1323 
1324         /* update p to point to new buffer */
1325         p = (UINT8 *)(p_ccb->p_rx_msg + 1) + p_ccb->p_rx_msg->offset;
1326 
1327         /* copy first header byte over nosp */
1328         *(p + 1) = *p;
1329 
1330         /* set offset to point to where to copy next */
1331         p_ccb->p_rx_msg->offset += p_ccb->p_rx_msg->len;
1332 
1333         /* adjust length for packet header */
1334         p_ccb->p_rx_msg->len -= 1;
1335 
1336         p_ret = NULL;
1337     }
1338     /* continue or end */
1339     else {
1340         /* if no reassembly in progress drop message */
1341         if (p_ccb->p_rx_msg == NULL) {
1342             osi_free(p_buf);
1343             AVDT_TRACE_WARNING("Pkt type=%d out of order\n", pkt_type);
1344             p_ret = NULL;
1345         } else {
1346             /* get size of buffer holding assembled message */
1347             buf_len = BT_DEFAULT_BUFFER_SIZE - sizeof(BT_HDR);
1348 
1349             /* adjust offset and len of fragment for header byte */
1350             p_buf->offset += AVDT_LEN_TYPE_CONT;
1351             p_buf->len -= AVDT_LEN_TYPE_CONT;
1352 
1353             /* verify length */
1354             if ((p_ccb->p_rx_msg->offset + p_buf->len) > buf_len) {
1355                 /* won't fit; free everything */
1356                 AVDT_TRACE_WARNING("%s: Fragmented message too big!", __func__);
1357                 osi_free(p_ccb->p_rx_msg);
1358                 p_ccb->p_rx_msg = NULL;
1359                 osi_free(p_buf);
1360                 p_ret = NULL;
1361             } else {
1362                 /* copy contents of p_buf to p_rx_msg */
1363                 memcpy((UINT8 *)(p_ccb->p_rx_msg + 1) + p_ccb->p_rx_msg->offset,
1364                        (UINT8 *)(p_buf + 1) + p_buf->offset, p_buf->len);
1365 
1366                 if (pkt_type == AVDT_PKT_TYPE_END) {
1367                     p_ccb->p_rx_msg->offset -= p_ccb->p_rx_msg->len;
1368                     p_ccb->p_rx_msg->len += p_buf->len;
1369                     p_ret = p_ccb->p_rx_msg;
1370                     p_ccb->p_rx_msg = NULL;
1371                 } else {
1372                     p_ccb->p_rx_msg->offset += p_buf->len;
1373                     p_ccb->p_rx_msg->len += p_buf->len;
1374                     p_ret = NULL;
1375                 }
1376                 osi_free(p_buf);
1377             }
1378         }
1379     }
1380     return p_ret;
1381 }
1382 
1383 /*******************************************************************************
1384 **
1385 ** Function         avdt_msg_send_cmd
1386 **
1387 ** Description      This function is called to send a command message.  The
1388 **                  sig_id parameter indicates the message type, p_params
1389 **                  points to the message parameters, if any.  It gets a buffer
1390 **                  from the AVDTP command pool, executes the message building
1391 **                  function for this message type.  It then queues the message
1392 **                  in the command queue for this CCB.
1393 **
1394 **
1395 ** Returns          Nothing.
1396 **
1397 *******************************************************************************/
avdt_msg_send_cmd(tAVDT_CCB * p_ccb,void * p_scb,UINT8 sig_id,tAVDT_MSG * p_params)1398 void avdt_msg_send_cmd(tAVDT_CCB *p_ccb, void *p_scb, UINT8 sig_id, tAVDT_MSG *p_params)
1399 {
1400     BT_HDR      *p_buf;
1401     UINT8       *p;
1402     UINT8       *p_start;
1403 
1404     /* get a buffer */
1405     p_buf = (BT_HDR *) osi_malloc(AVDT_CMD_BUF_SIZE);
1406     if (p_buf == NULL) {
1407         AVDT_TRACE_ERROR("avdt_msg_send_cmd out of buffer!!");
1408         return;
1409     }
1410 
1411     /* set up gki buf pointer and offset */
1412     p_buf->offset = AVDT_MSG_OFFSET;
1413     p_start = p = (UINT8 *)(p_buf + 1) + p_buf->offset;
1414 
1415     /* execute parameter building function to build message */
1416     (*avdt_msg_bld_cmd[sig_id - 1])(&p, p_params);
1417 
1418     /* set len */
1419     p_buf->len = (UINT16) (p - p_start);
1420 
1421     /* now store scb hdls, if any, in buf */
1422     if (p_scb != NULL) {
1423         p = (UINT8 *)(p_buf + 1);
1424 
1425         /* for start and suspend, p_scb points to array of handles */
1426         if ((sig_id == AVDT_SIG_START) || (sig_id == AVDT_SIG_SUSPEND)) {
1427             memcpy(p, (UINT8 *) p_scb, p_buf->len);
1428         }
1429         /* for all others, p_scb points to scb as usual */
1430         else {
1431             *p = avdt_scb_to_hdl((tAVDT_SCB *) p_scb);
1432         }
1433     }
1434 
1435     /* stash sig, label, and message type in buf */
1436     p_buf->event = sig_id;
1437     AVDT_BLD_LAYERSPEC(p_buf->layer_specific, AVDT_MSG_TYPE_CMD, p_ccb->label);
1438 
1439     /* increment label */
1440     p_ccb->label = (p_ccb->label + 1) % 16;
1441 
1442     /* queue message and trigger ccb to send it */
1443     fixed_queue_enqueue(p_ccb->cmd_q, p_buf, FIXED_QUEUE_MAX_TIMEOUT);
1444     avdt_ccb_event(p_ccb, AVDT_CCB_SENDMSG_EVT, NULL);
1445 }
1446 
1447 
1448 /*******************************************************************************
1449 **
1450 ** Function         avdt_msg_send_rsp
1451 **
1452 ** Description      This function is called to send a response message.  The
1453 **                  sig_id parameter indicates the message type, p_params
1454 **                  points to the message parameters, if any.  It gets a buffer
1455 **                  from the AVDTP command pool, executes the message building
1456 **                  function for this message type.  It then queues the message
1457 **                  in the response queue for this CCB.
1458 **
1459 **
1460 ** Returns          Nothing.
1461 **
1462 *******************************************************************************/
avdt_msg_send_rsp(tAVDT_CCB * p_ccb,UINT8 sig_id,tAVDT_MSG * p_params)1463 void avdt_msg_send_rsp(tAVDT_CCB *p_ccb, UINT8 sig_id, tAVDT_MSG *p_params)
1464 {
1465     BT_HDR      *p_buf;
1466     UINT8       *p;
1467     UINT8       *p_start;
1468 
1469     /* get a buffer */
1470     p_buf = (BT_HDR *) osi_malloc(AVDT_CMD_BUF_SIZE);
1471     if (p_buf == NULL) {
1472         return;
1473     }
1474 
1475     /* set up gki buf pointer and offset */
1476     p_buf->offset = AVDT_MSG_OFFSET;
1477     p_start = p = (UINT8 *)(p_buf + 1) + p_buf->offset;
1478 
1479     /* execute parameter building function to build message */
1480     (*avdt_msg_bld_rsp[sig_id - 1])(&p, p_params);
1481 
1482     /* set length */
1483     p_buf->len = (UINT16) (p - p_start);
1484 
1485     /* stash sig, label, and message type in buf */
1486     p_buf->event = sig_id;
1487     AVDT_BLD_LAYERSPEC(p_buf->layer_specific, AVDT_MSG_TYPE_RSP, p_params->hdr.label);
1488 
1489     /* queue message and trigger ccb to send it */
1490     fixed_queue_enqueue(p_ccb->rsp_q, p_buf, FIXED_QUEUE_MAX_TIMEOUT);
1491     avdt_ccb_event(p_ccb, AVDT_CCB_SENDMSG_EVT, NULL);
1492 }
1493 
1494 
1495 /*******************************************************************************
1496 **
1497 ** Function         avdt_msg_send_rej
1498 **
1499 ** Description      This function is called to send a reject message.  The
1500 **                  sig_id parameter indicates the message type.  It gets
1501 **                  a buffer from the AVDTP command pool and builds the
1502 **                  message based on the message type and the error code.
1503 **                  It then queues the message in the response queue for
1504 **                  this CCB.
1505 **
1506 **
1507 ** Returns          Nothing.
1508 **
1509 *******************************************************************************/
avdt_msg_send_rej(tAVDT_CCB * p_ccb,UINT8 sig_id,tAVDT_MSG * p_params)1510 void avdt_msg_send_rej(tAVDT_CCB *p_ccb, UINT8 sig_id, tAVDT_MSG *p_params)
1511 {
1512     BT_HDR      *p_buf;
1513     UINT8       *p;
1514     UINT8       *p_start;
1515 
1516     /* get a buffer */
1517     p_buf = (BT_HDR *) osi_malloc(AVDT_CMD_BUF_SIZE);
1518     if (p_buf == NULL) {
1519         return;
1520     }
1521 
1522     /* set up gki buf pointer and offset */
1523     p_buf->offset = AVDT_MSG_OFFSET;
1524     p_start = p = (UINT8 *)(p_buf + 1) + p_buf->offset;
1525 
1526     /* if sig id included, build into message */
1527     if (sig_id != AVDT_SIG_NONE) {
1528         /* if this sig has a parameter, add the parameter */
1529         if ((sig_id == AVDT_SIG_SETCONFIG) ||
1530                 (sig_id == AVDT_SIG_RECONFIG)) {
1531             AVDT_MSG_BLD_PARAM(p, p_params->hdr.err_param);
1532         } else if ((sig_id == AVDT_SIG_START) ||
1533                    (sig_id == AVDT_SIG_SUSPEND)) {
1534             AVDT_MSG_BLD_SEID(p, p_params->hdr.err_param);
1535         }
1536 
1537         /* add the error code */
1538         AVDT_MSG_BLD_ERR(p, p_params->hdr.err_code);
1539     }
1540     AVDT_TRACE_DEBUG("avdt_msg_send_rej");
1541 
1542     /* calculate length */
1543     p_buf->len = (UINT16) (p - p_start);
1544 
1545     /* stash sig, label, and message type in buf */
1546     p_buf->event = sig_id;
1547     AVDT_BLD_LAYERSPEC(p_buf->layer_specific, AVDT_MSG_TYPE_REJ, p_params->hdr.label);
1548 
1549     /* queue message and trigger ccb to send it */
1550     fixed_queue_enqueue(p_ccb->rsp_q, p_buf, FIXED_QUEUE_MAX_TIMEOUT);
1551     avdt_ccb_event(p_ccb, AVDT_CCB_SENDMSG_EVT, NULL);
1552 }
1553 
1554 /*******************************************************************************
1555 **
1556 ** Function         avdt_msg_send_grej
1557 **
1558 ** Description      This function is called to send a general reject message.  The
1559 **                  sig_id parameter indicates the message type.  It gets
1560 **                  a buffer from the AVDTP command pool and builds the
1561 **                  message based on the message type and the error code.
1562 **                  It then queues the message in the response queue for
1563 **                  this CCB.
1564 **
1565 **
1566 ** Returns          Nothing.
1567 **
1568 *******************************************************************************/
avdt_msg_send_grej(tAVDT_CCB * p_ccb,UINT8 sig_id,tAVDT_MSG * p_params)1569 void avdt_msg_send_grej(tAVDT_CCB *p_ccb, UINT8 sig_id, tAVDT_MSG *p_params)
1570 {
1571     BT_HDR      *p_buf;
1572     UINT8       *p;
1573     UINT8       *p_start;
1574 
1575     /* get a buffer */
1576     p_buf = (BT_HDR *) osi_malloc(AVDT_CMD_BUF_SIZE);
1577     if (p_buf == NULL) {
1578         return;
1579     }
1580 
1581     /* set up gki buf pointer and offset */
1582     p_buf->offset = AVDT_MSG_OFFSET;
1583     p_start = p = (UINT8 *)(p_buf + 1) + p_buf->offset;
1584 
1585     /* calculate length */
1586     p_buf->len = (UINT16) (p - p_start);
1587 
1588     /* stash sig, label, and message type in buf */
1589     p_buf->event = 0;
1590     AVDT_BLD_LAYERSPEC(p_buf->layer_specific, 0, p_params->hdr.label);
1591     AVDT_TRACE_DEBUG("avdt_msg_send_grej");
1592 
1593     /* queue message and trigger ccb to send it */
1594     fixed_queue_enqueue(p_ccb->rsp_q, p_buf, FIXED_QUEUE_MAX_TIMEOUT);
1595     avdt_ccb_event(p_ccb, AVDT_CCB_SENDMSG_EVT, NULL);
1596 }
1597 
1598 /*******************************************************************************
1599 **
1600 ** Function         avdt_msg_ind
1601 **
1602 ** Description      This function is called by the adaption layer when an
1603 **                  incoming message is received on the signaling channel.
1604 **                  It parses the message and sends an event to the appropriate
1605 **                  SCB or CCB for the message.
1606 **
1607 **
1608 ** Returns          Nothing.
1609 **
1610 *******************************************************************************/
avdt_msg_ind(tAVDT_CCB * p_ccb,BT_HDR * p_buf)1611 void avdt_msg_ind(tAVDT_CCB *p_ccb, BT_HDR *p_buf)
1612 {
1613     tAVDT_SCB   *p_scb;
1614     UINT8       *p;
1615     BOOLEAN     ok = TRUE;
1616     BOOLEAN     handle_rsp = FALSE;
1617     BOOLEAN     gen_rej = FALSE;
1618     UINT8       label;
1619     UINT8       pkt_type;
1620     UINT8       msg_type;
1621     UINT8       sig = 0;
1622     tAVDT_MSG   msg;
1623     tAVDT_CFG   cfg;
1624     UINT8       err;
1625     UINT8       evt = 0;
1626     UINT8       scb_hdl;
1627 
1628     /* reassemble message; if no message available (we received a fragment) return */
1629     if ((p_buf = avdt_msg_asmbl(p_ccb, p_buf)) == NULL) {
1630         return;
1631     }
1632 
1633     p = (UINT8 *)(p_buf + 1) + p_buf->offset;
1634 
1635     /* parse the message header */
1636     AVDT_MSG_PRS_HDR(p, label, pkt_type, msg_type);
1637 
1638     UNUSED(pkt_type);
1639 
1640     AVDT_TRACE_DEBUG("msg_type=%d, sig=%d\n", msg_type, sig);
1641     /* set up label and ccb_idx in message hdr */
1642     msg.hdr.label = label;
1643     msg.hdr.ccb_idx = avdt_ccb_to_idx(p_ccb);
1644 
1645     /* verify msg type */
1646     if (msg_type == AVDT_MSG_TYPE_GRJ) {
1647         AVDT_TRACE_WARNING("Dropping msg msg_type=%d\n", msg_type);
1648         ok = FALSE;
1649     }
1650     /* check for general reject */
1651     else if ((msg_type == AVDT_MSG_TYPE_REJ) && (p_buf->len == AVDT_LEN_GEN_REJ)) {
1652         gen_rej = TRUE;
1653         if (p_ccb->p_curr_cmd != NULL) {
1654             msg.hdr.sig_id = sig = (UINT8) p_ccb->p_curr_cmd->event;
1655             evt = avdt_msg_rej_2_evt[sig - 1];
1656             msg.hdr.err_code = AVDT_ERR_NSC;
1657             msg.hdr.err_param = 0;
1658         }
1659     } else { /* not a general reject */
1660         /* get and verify signal */
1661         AVDT_MSG_PRS_SIG(p, sig);
1662         msg.hdr.sig_id = sig;
1663         if ((sig == 0) || (sig > AVDT_SIG_MAX)) {
1664             AVDT_TRACE_WARNING("Dropping msg sig=%d msg_type:%d\n", sig, msg_type);
1665             ok = FALSE;
1666 
1667             /* send a general reject */
1668             if (msg_type == AVDT_MSG_TYPE_CMD) {
1669                 avdt_msg_send_grej(p_ccb, sig, &msg);
1670             }
1671         }
1672     }
1673 
1674     if (ok && !gen_rej) {
1675         /* skip over header (msg length already verified during reassembly) */
1676         p_buf->len -= AVDT_LEN_TYPE_SINGLE;
1677 
1678         /* set up to parse message */
1679         if ((msg_type == AVDT_MSG_TYPE_RSP) && (sig == AVDT_SIG_DISCOVER)) {
1680             /* parse discover rsp message to struct supplied by app */
1681             msg.discover_rsp.p_sep_info = (tAVDT_SEP_INFO *) p_ccb->p_proc_data;
1682             msg.discover_rsp.num_seps = p_ccb->proc_param;
1683         } else if ((msg_type == AVDT_MSG_TYPE_RSP) &&
1684                    ((sig == AVDT_SIG_GETCAP) || (sig == AVDT_SIG_GET_ALLCAP))) {
1685             /* parse discover rsp message to struct supplied by app */
1686             msg.svccap.p_cfg = (tAVDT_CFG *) p_ccb->p_proc_data;
1687         } else if ((msg_type == AVDT_MSG_TYPE_RSP) && (sig == AVDT_SIG_GETCONFIG)) {
1688             /* parse get config rsp message to struct allocated locally */
1689             msg.svccap.p_cfg = &cfg;
1690         } else if ((msg_type == AVDT_MSG_TYPE_CMD) && (sig == AVDT_SIG_SETCONFIG)) {
1691             /* parse config cmd message to struct allocated locally */
1692             msg.config_cmd.p_cfg = &cfg;
1693         } else if ((msg_type == AVDT_MSG_TYPE_CMD) && (sig == AVDT_SIG_RECONFIG)) {
1694             /* parse reconfig cmd message to struct allocated locally */
1695             msg.reconfig_cmd.p_cfg = &cfg;
1696         }
1697 
1698         /* parse message; while we're at it map message sig to event */
1699         if (msg_type == AVDT_MSG_TYPE_CMD) {
1700             msg.hdr.err_code = err = (*avdt_msg_prs_cmd[sig - 1])(&msg, p, p_buf->len);
1701             evt = avdt_msg_cmd_2_evt[sig - 1];
1702         } else if (msg_type == AVDT_MSG_TYPE_RSP) {
1703             msg.hdr.err_code = err = (*avdt_msg_prs_rsp[sig - 1])(&msg, p, p_buf->len);
1704             evt = avdt_msg_rsp_2_evt[sig - 1];
1705         } else { /* msg_type == AVDT_MSG_TYPE_REJ */
1706             err = avdt_msg_prs_rej(&msg, p, sig);
1707             evt = avdt_msg_rej_2_evt[sig - 1];
1708         }
1709 
1710         /* if parsing failed */
1711         if (err != 0) {
1712             AVDT_TRACE_WARNING("Parsing failed sig=%d err=0x%x\n", sig, err);
1713 
1714             /* if its a rsp or rej, drop it; if its a cmd, send a rej;
1715             ** note special case for abort; never send abort reject
1716             */
1717             ok = FALSE;
1718             if ((msg_type == AVDT_MSG_TYPE_CMD) && (sig != AVDT_SIG_ABORT)) {
1719                 avdt_msg_send_rej(p_ccb, sig, &msg);
1720             }
1721         }
1722     }
1723 
1724     /* if its a rsp or rej, check sent cmd to see if we're waiting for
1725     ** the rsp or rej.  If we didn't send a cmd for it, drop it.  If
1726     ** it does match a cmd, stop timer for the cmd.
1727     */
1728     if (ok) {
1729         if ((msg_type == AVDT_MSG_TYPE_RSP) || (msg_type == AVDT_MSG_TYPE_REJ)) {
1730             if ((p_ccb->p_curr_cmd != NULL) &&
1731                     (p_ccb->p_curr_cmd->event == sig) &&
1732                     (AVDT_LAYERSPEC_LABEL(p_ccb->p_curr_cmd->layer_specific) == label)) {
1733                 /* stop timer */
1734                 btu_stop_timer(&p_ccb->timer_entry);
1735 
1736                 /* clear retransmission count */
1737                 p_ccb->ret_count = 0;
1738 
1739                 /* later in this function handle ccb event */
1740                 handle_rsp = TRUE;
1741             } else {
1742                 ok = FALSE;
1743                 AVDT_TRACE_WARNING("Cmd not found for rsp sig=%d label=%d\n", sig, label);
1744             }
1745         }
1746     }
1747 
1748     if (ok) {
1749         /* if it's a ccb event send to ccb */
1750         if (evt & AVDT_CCB_MKR) {
1751             avdt_ccb_event(p_ccb, (UINT8)(evt & ~AVDT_CCB_MKR), (tAVDT_CCB_EVT *) &msg);
1752         }
1753         /* if it's a scb event */
1754         else {
1755             /* Scb events always have a single seid.  For cmd, get seid from
1756             ** message.  For rej and rsp, get seid from p_curr_cmd.
1757             */
1758             if (msg_type == AVDT_MSG_TYPE_CMD) {
1759                 scb_hdl = msg.single.seid;
1760             } else {
1761                 scb_hdl = *((UINT8 *)(p_ccb->p_curr_cmd + 1));
1762             }
1763 
1764             /* Map seid to the scb and send it the event.  For cmd, seid has
1765             ** already been verified by parsing function.
1766             */
1767             if (evt && (p_scb = avdt_scb_by_hdl(scb_hdl)) != NULL) {
1768                 avdt_scb_event(p_scb, evt, (tAVDT_SCB_EVT *) &msg);
1769             }
1770         }
1771     }
1772 
1773     /* free message buffer */
1774     osi_free(p_buf);
1775 
1776     /* if its a rsp or rej, send event to ccb to free associated
1777     ** cmd msg buffer and handle cmd queue
1778     */
1779     if (handle_rsp) {
1780         avdt_ccb_event(p_ccb, AVDT_CCB_RCVRSP_EVT, NULL);
1781     }
1782 }
1783 
1784 #endif /* #if (defined(AVDT_INCLUDED) && AVDT_INCLUDED == TRUE) */
1785