23
23
#include <zephyr/bluetooth/classic/avdtp.h>
24
24
#include <zephyr/bluetooth/classic/a2dp_codec_sbc.h>
25
25
#include <zephyr/bluetooth/classic/a2dp.h>
26
+ #include <zephyr/bluetooth/classic/sdp.h>
26
27
27
28
#include "common/assert.h"
28
29
@@ -65,6 +66,7 @@ struct bt_a2dp {
65
66
struct bt_avdtp_get_capabilities_params get_capabilities_param ;
66
67
struct bt_avdtp_set_configuration_params set_config_param ;
67
68
struct bt_avdtp_ctrl_params ctrl_param ;
69
+ uint16_t avdtp_version ;
68
70
uint8_t get_cap_index ;
69
71
enum bt_a2dp_internal_state a2dp_state ;
70
72
uint8_t peer_seps_count ;
@@ -125,8 +127,13 @@ static int a2dp_discovery_ind(struct bt_avdtp *session, uint8_t *errcode)
125
127
}
126
128
127
129
static int a2dp_get_capabilities_ind (struct bt_avdtp * session , struct bt_avdtp_sep * sep ,
128
- struct net_buf * rsp_buf , uint8_t * errcode )
130
+ struct net_buf * rsp_buf , bool get_all_caps , uint8_t * errcode )
129
131
{
132
+ /* The Reporting, Recovery, Content Protection, Header Compression, Multiplexing and
133
+ * Delay Reporting services are not supported, so the same response is replied as
134
+ * get_capabilities.
135
+ */
136
+ ARG_UNUSED (get_all_caps );
130
137
struct bt_a2dp_ep * ep ;
131
138
132
139
__ASSERT (sep , "Invalid sep" );
@@ -505,6 +512,19 @@ static int bt_a2dp_get_sep_caps(struct bt_a2dp *a2dp)
505
512
a2dp -> get_capabilities_param .req .func = bt_a2dp_get_capabilities_cb ;
506
513
a2dp -> get_capabilities_param .stream_endpoint_id =
507
514
a2dp -> discover_cb_param -> seps_info [a2dp -> get_cap_index ].id ;
515
+
516
+ /* The legacy Get Capabilities procedure is deprecated in cases
517
+ * where backwards compatibility with AVDTP 1.2 and earlier is irrelevant.
518
+ */
519
+ #if (AVDTP_VERSION >= AVDTP_VERSION_1_3 )
520
+ if (a2dp -> avdtp_version >= AVDTP_VERSION_1_3 ) {
521
+ a2dp -> get_capabilities_param .get_all_caps = true;
522
+ } else {
523
+ #endif /* AVDTP_VERSION >= AVDTP_VERSION_1_3 */
524
+ a2dp -> get_capabilities_param .get_all_caps = false;
525
+ #if (AVDTP_VERSION >= AVDTP_VERSION_1_3 )
526
+ }
527
+ #endif /* AVDTP_VERSION >= AVDTP_VERSION_1_3 */
508
528
err = bt_avdtp_get_capabilities (& a2dp -> session ,
509
529
& a2dp -> get_capabilities_param );
510
530
@@ -575,6 +595,145 @@ static int bt_a2dp_discover_cb(struct bt_avdtp_req *req, struct net_buf *buf)
575
595
return 0 ;
576
596
}
577
597
598
+ static void bt_a2dp_end_discover (struct bt_a2dp * a2dp )
599
+ {
600
+ if (a2dp -> discover_cb_param != NULL ) {
601
+ if (a2dp -> discover_cb_param -> cb != NULL ) {
602
+ a2dp -> discover_cb_param -> cb (a2dp , NULL , NULL );
603
+ }
604
+ a2dp -> discover_cb_param = NULL ;
605
+ }
606
+ }
607
+
608
+ static int bt_a2dp_trigger_discover (struct bt_a2dp * a2dp )
609
+ {
610
+ int err ;
611
+
612
+ if (a2dp -> discover_cb_param == NULL ) {
613
+ return - EINVAL ;
614
+ }
615
+
616
+ a2dp -> discover_param .req .func = bt_a2dp_discover_cb ;
617
+
618
+ err = bt_avdtp_discover (& a2dp -> session , & a2dp -> discover_param );
619
+ if (err != 0 ) {
620
+ bt_a2dp_end_discover (a2dp );
621
+ }
622
+
623
+ return err ;
624
+ }
625
+
626
+ #if defined(CONFIG_BT_A2DP_SOURCE ) || defined(CONFIG_BT_A2DP_SINK )
627
+ #define A2DP_SERVICE_LEN 512
628
+ NET_BUF_POOL_FIXED_DEFINE (find_avdtp_version_pool , 1 , A2DP_SERVICE_LEN ,
629
+ CONFIG_BT_CONN_TX_USER_DATA_SIZE , NULL );
630
+
631
+ static const struct bt_uuid * a2dp_snk_uuid = BT_UUID_DECLARE_16 (BT_SDP_AUDIO_SINK_SVCLASS );
632
+ static const struct bt_uuid * a2dp_src_uuid = BT_UUID_DECLARE_16 (BT_SDP_AUDIO_SOURCE_SVCLASS );
633
+ static struct bt_sdp_discover_params discov_a2dp = {
634
+ .type = BT_SDP_DISCOVER_SERVICE_SEARCH_ATTR ,
635
+ .pool = & find_avdtp_version_pool ,
636
+ };
637
+ #endif
638
+
639
+ #if defined(CONFIG_BT_A2DP_SINK )
640
+ static uint8_t sdp_discover_audio_src_func (struct bt_conn * conn ,
641
+ struct bt_sdp_client_result * result ,
642
+ const struct bt_sdp_discover_params * params )
643
+ {
644
+ int err ;
645
+ uint16_t version ;
646
+ struct bt_a2dp * a2dp = & connection [bt_conn_index (conn )];
647
+
648
+ if ((result == NULL ) || (result -> resp_buf == NULL ) || (result -> resp_buf -> len == 0 )) {
649
+ bt_a2dp_end_discover (a2dp );
650
+
651
+ return BT_SDP_DISCOVER_UUID_STOP ;
652
+ }
653
+
654
+ err = bt_sdp_get_proto_param (result -> resp_buf , BT_SDP_PROTO_AVDTP , & version );
655
+ if (err != 0 ) {
656
+ bt_a2dp_end_discover (a2dp );
657
+ } else {
658
+ a2dp -> avdtp_version = version ;
659
+
660
+ (void )bt_a2dp_trigger_discover (a2dp );
661
+ }
662
+
663
+ return BT_SDP_DISCOVER_UUID_STOP ;
664
+ }
665
+
666
+ static int bt_a2dp_find_audio_src_sdp_service (struct bt_a2dp * a2dp )
667
+ {
668
+ int err ;
669
+ struct bt_conn * conn ;
670
+
671
+ conn = bt_a2dp_get_conn (a2dp );
672
+ if (conn == NULL ) {
673
+ return - ENOTCONN ;
674
+ }
675
+
676
+ discov_a2dp .uuid = a2dp_src_uuid ;
677
+ discov_a2dp .func = sdp_discover_audio_src_func ;
678
+ err = bt_sdp_discover (conn , & discov_a2dp );
679
+ bt_conn_unref (conn );
680
+
681
+ return err ;
682
+ }
683
+ #endif
684
+
685
+ #if defined(CONFIG_BT_A2DP_SOURCE )
686
+ static uint8_t sdp_discover_audio_snk_func (struct bt_conn * conn ,
687
+ struct bt_sdp_client_result * result ,
688
+ const struct bt_sdp_discover_params * params )
689
+ {
690
+ int err ;
691
+ uint16_t version ;
692
+ struct bt_a2dp * a2dp = & connection [bt_conn_index (conn )];
693
+
694
+ if ((result == NULL ) || (result -> resp_buf == NULL ) || (result -> resp_buf -> len == 0 )) {
695
+ #if defined(CONFIG_BT_A2DP_SINK )
696
+ err = bt_a2dp_find_audio_src_sdp_service (a2dp );
697
+ if (err != 0 ) {
698
+ bt_a2dp_end_discover (a2dp );
699
+ }
700
+ #else
701
+ bt_a2dp_end_discover (a2dp );
702
+ #endif
703
+ return BT_SDP_DISCOVER_UUID_STOP ;
704
+ }
705
+
706
+ err = bt_sdp_get_proto_param (result -> resp_buf , BT_SDP_PROTO_AVDTP , & version );
707
+ if (err != 0 ) {
708
+ bt_a2dp_end_discover (a2dp );
709
+ } else {
710
+ a2dp -> avdtp_version = version ;
711
+
712
+ (void )bt_a2dp_trigger_discover (a2dp );
713
+ }
714
+
715
+ return BT_SDP_DISCOVER_UUID_STOP ;
716
+ }
717
+
718
+ static int bt_a2dp_find_audio_snk_sdp_service (struct bt_a2dp * a2dp )
719
+ {
720
+ int err ;
721
+ struct bt_conn * conn ;
722
+
723
+ conn = bt_a2dp_get_conn (a2dp );
724
+ if (conn == NULL ) {
725
+ return - ENOTCONN ;
726
+ }
727
+
728
+ discov_a2dp .uuid = a2dp_snk_uuid ;
729
+ discov_a2dp .func = sdp_discover_audio_snk_func ;
730
+ err = bt_sdp_discover (conn , & discov_a2dp );
731
+ bt_conn_unref (conn );
732
+
733
+ return err ;
734
+ }
735
+ #endif
736
+
578
737
int bt_a2dp_discover (struct bt_a2dp * a2dp , struct bt_a2dp_discover_param * param )
579
738
{
580
739
int err ;
@@ -591,17 +750,20 @@ int bt_a2dp_discover(struct bt_a2dp *a2dp, struct bt_a2dp_discover_param *param)
591
750
return - EBUSY ;
592
751
}
593
752
594
- memset (& a2dp -> discover_cb_param , 0U , sizeof (a2dp -> discover_cb_param ));
595
753
a2dp -> discover_cb_param = param ;
596
- a2dp -> discover_param .req .func = bt_a2dp_discover_cb ;
597
-
598
- err = bt_avdtp_discover (& a2dp -> session , & a2dp -> discover_param );
599
- if (err ) {
600
- if (a2dp -> discover_cb_param -> cb != NULL ) {
601
- a2dp -> discover_cb_param -> cb (a2dp , NULL , NULL );
754
+ if (param -> avdtp_version == 0 && a2dp -> avdtp_version == 0 ) {
755
+ /* try to get the peer's sdp a2dp service's avdtp version */
756
+ #if defined(CONFIG_BT_A2DP_SOURCE )
757
+ err = bt_a2dp_find_audio_snk_sdp_service (a2dp );
758
+ #elif defined(CONFIG_BT_A2DP_SINK )
759
+ err = bt_a2dp_find_audio_src_sdp_service (a2dp );
760
+ #endif
761
+ } else {
762
+ if (param -> avdtp_version != 0 ) {
763
+ a2dp -> avdtp_version = param -> avdtp_version ;
602
764
}
603
765
604
- a2dp -> discover_cb_param = NULL ;
766
+ err = bt_a2dp_trigger_discover ( a2dp ) ;
605
767
}
606
768
607
769
return err ;
0 commit comments