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