Skip to content

Commit 2768acb

Browse files
CC0918kartben
authored andcommitted
bluetooth: host: avdtp: Fix command and response format error
There are three aspects of changes involved: 1. The format of Service Category should be checked in set configuration cmd and error code and Service Category should be detailed in response. 2. There is no INT Stream Endpoint ID in re_config cmd,. 3. Fail ACP SEID should be added to start and suspend rej rsp. Signed-off-by: Cheng Chang <[email protected]>
1 parent b83267d commit 2768acb

File tree

4 files changed

+188
-18
lines changed

4 files changed

+188
-18
lines changed

include/zephyr/bluetooth/classic/avdtp.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,14 @@ enum bt_avdtp_service_category {
124124
BT_AVDTP_SERVICE_DELAY_REPORTING = 0x08,
125125
};
126126

127+
/** @brief service category Recovery Capabilities type*/
128+
enum bt_avdtp_recovery_type {
129+
/** Forbidden */
130+
BT_AVDTP_RECOVERY_TYPE_FORBIDDEN = 0x00,
131+
/** RFC2733 */
132+
BT_ADVTP_RECOVERY_TYPE_RFC2733 = 0x01,
133+
};
134+
127135
/** @brief AVDTP Stream End Point */
128136
struct bt_avdtp_sep {
129137
/** Stream End Point information */

subsys/bluetooth/host/classic/a2dp.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -368,11 +368,11 @@ static int a2dp_set_config_ind(struct bt_avdtp *session, struct bt_avdtp_sep *se
368368
return a2dp_process_config_ind(session, sep, int_seid, buf, errcode, false);
369369
}
370370

371-
static int a2dp_re_config_ind(struct bt_avdtp *session, struct bt_avdtp_sep *sep, uint8_t int_seid,
371+
static int a2dp_re_config_ind(struct bt_avdtp *session, struct bt_avdtp_sep *sep,
372372
struct net_buf *buf, uint8_t *errcode)
373373
{
374374
__ASSERT(sep, "Invalid sep");
375-
return a2dp_process_config_ind(session, sep, int_seid, buf, errcode, true);
375+
return a2dp_process_config_ind(session, sep, 0, buf, errcode, true);
376376
}
377377

378378
#if defined(CONFIG_BT_A2DP_SINK)

subsys/bluetooth/host/classic/avdtp.c

Lines changed: 129 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -436,13 +436,108 @@ static void avdtp_get_capabilities_rsp(struct bt_avdtp *session, struct net_buf
436436
}
437437
}
438438

439+
struct bt_avdtp_service_category_handler {
440+
uint8_t min_len;
441+
uint8_t max_len;
442+
bool reconfig_support;
443+
uint8_t err_code;
444+
uint8_t (*handler)(struct net_buf *buf);
445+
};
446+
447+
uint8_t bt_avdtp_check_media_recovery_type(struct net_buf *buf)
448+
{
449+
struct bt_avdtp_recovery_capabilities *cap
450+
= (struct bt_avdtp_recovery_capabilities *)buf->data;
451+
452+
if (cap->recovery_type != BT_AVDTP_RECOVERY_TYPE_FORBIDDEN &&
453+
cap->recovery_type != BT_ADVTP_RECOVERY_TYPE_RFC2733) {
454+
return BT_AVDTP_BAD_RECOVERY_TYPE;
455+
}
456+
return BT_AVDTP_SUCCESS;
457+
}
458+
459+
static struct bt_avdtp_service_category_handler category_handler[] = {
460+
{0, 0, false, 0, NULL}, /*None*/
461+
{0, 0, false, BT_AVDTP_BAD_MEDIA_TRANSPORT_FORMAT,
462+
NULL}, /*BT_AVDTP_SERVICE_MEDIA_TRANSPORT*/
463+
{0, 0, false, BT_AVDTP_BAD_LENGTH, NULL}, /*BT_AVDTP_SERVICE_REPORTING*/
464+
{sizeof(struct bt_avdtp_recovery_capabilities),
465+
sizeof(struct bt_avdtp_recovery_capabilities), false, BT_AVDTP_BAD_RECOVERY_FORMAT,
466+
bt_avdtp_check_media_recovery_type}, /*BT_AVDTP_SERVICE_MEDIA_RECOVERY*/
467+
{sizeof(struct bt_avdtp_content_protection_capabilities), UINT8_MAX,
468+
true, BT_AVDTP_BAD_CP_FORMAT, NULL}, /*BT_AVDTP_SERVICE_CONTENT_PROTECTION*/
469+
{sizeof(struct bt_avdtp_header_compression_capabilities),
470+
sizeof(struct bt_avdtp_header_compression_capabilities),
471+
false, BT_AVDTP_BAD_LENGTH, NULL}, /*BT_AVDTP_SERVICE_HEADER_COMPRESSION*/
472+
{sizeof(struct bt_avdtp_multiplexing_capabilities),
473+
sizeof(struct bt_avdtp_multiplexing_capabilities),
474+
false, BT_AVDTP_BAD_MULTIPLEXING_FORMAT, NULL}, /*BT_AVDTP_SERVICE_MULTIPLEXING*/
475+
{sizeof(struct bt_avdtp_media_codec_capabilities), UINT8_MAX,
476+
true, BT_AVDTP_BAD_LENGTH, NULL}, /*BT_AVDTP_SERVICE_MEDIA_CODEC*/
477+
{0, 0, 0, BT_AVDTP_BAD_LENGTH, NULL}, /*BT_AVDTP_SERVICE_DELAY_REPORTING*/
478+
};
479+
480+
uint8_t bt_avdtp_check_service_category(struct net_buf *buf, uint8_t *service_category,
481+
bool reconfig)
482+
{
483+
struct bt_avdtp_generic_service_cap *hdr;
484+
uint8_t err;
485+
struct bt_avdtp_service_category_handler *handler;
486+
struct net_buf_simple_state state;
487+
488+
if (buf->len == 0U) {
489+
LOG_DBG("Error: buf not valid");
490+
return BT_AVDTP_BAD_LENGTH;
491+
}
492+
493+
while (buf->len > 0U) {
494+
if (buf->len < sizeof(*hdr)) {
495+
LOG_DBG("Error: buf not valid");
496+
return BT_AVDTP_BAD_LENGTH;
497+
}
498+
499+
hdr = net_buf_pull_mem(buf, sizeof(*hdr));
500+
*service_category = hdr->service_category;
501+
502+
if (hdr->service_category != 0 &&
503+
hdr->service_category < ARRAY_SIZE(category_handler)) {
504+
handler = &category_handler[hdr->service_category];
505+
506+
if (hdr->losc > buf->len || hdr->losc > handler->max_len ||
507+
hdr->losc < handler->min_len) {
508+
return handler->err_code;
509+
}
510+
511+
if (!handler->reconfig_support && reconfig) {
512+
return BT_AVDTP_INVALID_CAPABILITIES;
513+
}
514+
515+
if (handler->handler != NULL) {
516+
net_buf_simple_save(&buf->b, &state);
517+
err = handler->handler(buf);
518+
net_buf_simple_restore(&buf->b, &state);
519+
if (err != BT_AVDTP_SUCCESS) {
520+
return err;
521+
}
522+
}
523+
net_buf_pull_mem(buf, hdr->losc);
524+
} else {
525+
return BT_AVDTP_BAD_SERV_CATEGORY;
526+
}
527+
}
528+
529+
return BT_AVDTP_SUCCESS;
530+
}
531+
439532
static void avdtp_process_configuration_cmd(struct bt_avdtp *session, struct net_buf *buf,
440533
uint8_t tid, bool reconfig)
441534
{
442535
int err = 0;
443536
struct bt_avdtp_sep *sep;
444537
struct net_buf *rsp_buf;
445538
uint8_t avdtp_err_code = 0;
539+
struct net_buf_simple_state state;
540+
uint8_t service_category = 0;
446541

447542
sep = avdtp_get_cmd_sep(buf, &avdtp_err_code);
448543
avdtp_sep_lock(sep);
@@ -453,6 +548,9 @@ static void avdtp_process_configuration_cmd(struct bt_avdtp *session, struct net
453548
err = -ENOTSUP;
454549
} else if (reconfig && session->ops->re_configuration_ind == NULL) {
455550
err = -ENOTSUP;
551+
} else if (!reconfig && sep->sep_info.inuse == 1) {
552+
avdtp_err_code = BT_AVDTP_SEP_IN_USE;
553+
err = -EBUSY;
456554
} else {
457555
uint8_t expected_state;
458556

@@ -466,17 +564,29 @@ static void avdtp_process_configuration_cmd(struct bt_avdtp *session, struct net
466564
err = -ENOTSUP;
467565
avdtp_err_code = BT_AVDTP_BAD_STATE;
468566
} else if (buf->len >= 1U) {
469-
uint8_t int_seid;
567+
uint8_t int_seid = 0;
568+
uint8_t err_code = 0;
470569

471570
/* INT Stream Endpoint ID */
472-
int_seid = net_buf_pull_u8(buf) >> 2;
473-
474571
if (!reconfig) {
475-
err = session->ops->set_configuration_ind(session, sep, int_seid,
476-
buf, &avdtp_err_code);
572+
/* int seid not in reconfig cmd*/
573+
int_seid = net_buf_pull_u8(buf) >> 2;
574+
}
575+
net_buf_simple_save(&buf->b, &state);
576+
err_code = bt_avdtp_check_service_category(buf, &service_category,
577+
reconfig);
578+
net_buf_simple_restore(&buf->b, &state);
579+
if (err_code) {
580+
avdtp_err_code = err_code;
581+
err = -ENOTSUP;
477582
} else {
478-
err = session->ops->re_configuration_ind(session, sep, int_seid,
479-
buf, &avdtp_err_code);
583+
if (!reconfig) {
584+
err = session->ops->set_configuration_ind(
585+
session, sep, int_seid, buf, &avdtp_err_code);
586+
} else {
587+
err = session->ops->re_configuration_ind(session, sep, buf,
588+
&avdtp_err_code);
589+
}
480590
}
481591
} else {
482592
LOG_WRN("Invalid INT SEID");
@@ -499,8 +609,8 @@ static void avdtp_process_configuration_cmd(struct bt_avdtp *session, struct net
499609
}
500610

501611
LOG_DBG("set configuration err code:%d", avdtp_err_code);
502-
/* Service Category: Media Codec */
503-
net_buf_add_u8(rsp_buf, BT_AVDTP_SERVICE_MEDIA_CODEC);
612+
/* error Service Category*/
613+
net_buf_add_u8(rsp_buf, service_category);
504614
/* ERROR CODE */
505615
net_buf_add_u8(rsp_buf, avdtp_err_code);
506616
}
@@ -705,6 +815,7 @@ static void avdtp_start_cmd(struct bt_avdtp *session, struct net_buf *buf, uint8
705815
}
706816

707817
LOG_DBG("start err code:%d", avdtp_err_code);
818+
net_buf_add_u8(rsp_buf, sep->sep_info.id << 2);
708819
net_buf_add_u8(rsp_buf, avdtp_err_code);
709820
}
710821

@@ -860,6 +971,7 @@ static void avdtp_suspend_cmd(struct bt_avdtp *session, struct net_buf *buf, uin
860971
}
861972

862973
LOG_DBG("suspend err code:%d", avdtp_err_code);
974+
net_buf_add_u8(rsp_buf, sep->sep_info.id << 2);
863975
net_buf_add_u8(rsp_buf, avdtp_err_code);
864976
}
865977

@@ -1555,12 +1667,14 @@ static int avdtp_process_configure_command(struct bt_avdtp *session, uint8_t cmd
15551667
/* Body of the message */
15561668
/* ACP Stream Endpoint ID */
15571669
net_buf_add_u8(buf, (param->acp_stream_ep_id << 2U));
1558-
/* INT Stream Endpoint ID */
1559-
net_buf_add_u8(buf, (param->int_stream_endpoint_id << 2U));
1560-
/* Service Category: Media Transport */
1561-
net_buf_add_u8(buf, BT_AVDTP_SERVICE_MEDIA_TRANSPORT);
1562-
/* LOSC */
1563-
net_buf_add_u8(buf, 0);
1670+
if (cmd == BT_AVDTP_SET_CONFIGURATION) {
1671+
/* INT Stream Endpoint ID */
1672+
net_buf_add_u8(buf, (param->int_stream_endpoint_id << 2U));
1673+
/* Service Category: Media Transport */
1674+
net_buf_add_u8(buf, BT_AVDTP_SERVICE_MEDIA_TRANSPORT);
1675+
/* LOSC */
1676+
net_buf_add_u8(buf, 0);
1677+
}
15641678
/* Service Category: Media Codec */
15651679
net_buf_add_u8(buf, BT_AVDTP_SERVICE_MEDIA_CODEC);
15661680
/* LOSC */

subsys/bluetooth/host/classic/avdtp_internal.h

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,54 @@ struct bt_avdtp_ctrl_params {
174174
uint8_t acp_stream_ep_id;
175175
};
176176

177+
struct bt_avdtp_generic_service_cap {
178+
uint8_t service_category;
179+
uint8_t losc;
180+
} __packed;
181+
182+
/* avdtp service capabilities*/
183+
struct bt_avdtp_recovery_capabilities {
184+
uint8_t recovery_type;
185+
uint8_t MRWS;
186+
uint8_t MNMP;
187+
} __packed;
188+
189+
struct bt_avdtp_media_codec_capabilities {
190+
uint8_t media_type;
191+
uint8_t media_code_type;
192+
uint8_t media_codec_spec_info[0];
193+
} __packed;
194+
195+
struct bt_avdtp_content_protection_capabilities {
196+
uint8_t cp_type_lsb;
197+
uint8_t cp_type_msb;
198+
uint8_t cp_type_spec_value[0];
199+
} __packed;
200+
201+
struct bt_avdtp_header_compression_capabilities {
202+
#ifdef CONFIG_LITTLE_ENDIAN
203+
uint8_t reserved : 5;
204+
uint8_t recovery : 1;
205+
uint8_t media : 1;
206+
uint8_t backch : 1;
207+
#else
208+
uint8_t backch : 1;
209+
uint8_t media : 1;
210+
uint8_t recovery : 1;
211+
uint8_t reserved : 5;
212+
#endif /* CONFIG_LITTLE_ENDIAN */
213+
} __packed;
214+
215+
struct bt_avdtp_multiplexing_capabilities {
216+
uint8_t frag;
217+
uint8_t tsid_media;
218+
uint8_t tcid_media;
219+
uint8_t tsid_reporting;
220+
uint8_t tcid_reporting;
221+
uint8_t tsid_recovery;
222+
uint8_t tcid_recovery;
223+
} __packed;
224+
177225
struct bt_avdtp_ops_cb {
178226
void (*connected)(struct bt_avdtp *session);
179227

@@ -190,7 +238,7 @@ struct bt_avdtp_ops_cb {
190238
uint8_t int_seid, struct net_buf *buf, uint8_t *errcode);
191239

192240
int (*re_configuration_ind)(struct bt_avdtp *session, struct bt_avdtp_sep *sep,
193-
uint8_t int_seid, struct net_buf *buf, uint8_t *errcode);
241+
struct net_buf *buf, uint8_t *errcode);
194242

195243
int (*open_ind)(struct bt_avdtp *session, struct bt_avdtp_sep *sep, uint8_t *errcode);
196244

0 commit comments

Comments
 (0)