17
17
18
18
#include <zephyr/bluetooth/classic/rfcomm.h>
19
19
#include <zephyr/bluetooth/classic/hfp_ag.h>
20
+ #include <zephyr/bluetooth/classic/sdp.h>
20
21
21
22
#include "host/hci_core.h"
22
23
#include "host/conn_internal.h"
@@ -79,9 +80,78 @@ static struct bt_ag_tx ag_tx[CONFIG_BT_HFP_AG_TX_BUF_COUNT * 2];
79
80
static K_FIFO_DEFINE (ag_tx_free );
80
81
static K_FIFO_DEFINE (ag_tx_notify );
81
82
82
- struct k_thread ag_thread ;
83
- static K_KERNEL_STACK_MEMBER (ag_thread_stack , CONFIG_BT_HFP_AG_THREAD_STACK_SIZE ) ;
84
- static k_tid_t ag_thread_id ;
83
+ /* HFP Gateway SDP record */
84
+ static struct bt_sdp_attribute hfp_ag_attrs [] = {
85
+ BT_SDP_NEW_SERVICE ,
86
+ BT_SDP_LIST (
87
+ BT_SDP_ATTR_SVCLASS_ID_LIST ,
88
+ BT_SDP_TYPE_SIZE_VAR (BT_SDP_SEQ8 , 6 ),
89
+ BT_SDP_DATA_ELEM_LIST (
90
+ {
91
+ BT_SDP_TYPE_SIZE (BT_SDP_UUID16 ),
92
+ BT_SDP_ARRAY_16 (BT_SDP_HANDSFREE_AGW_SVCLASS )
93
+ },
94
+ {
95
+ BT_SDP_TYPE_SIZE (BT_SDP_UUID16 ),
96
+ BT_SDP_ARRAY_16 (BT_SDP_GENERIC_AUDIO_SVCLASS )
97
+ }
98
+ )
99
+ ),
100
+ BT_SDP_LIST (
101
+ BT_SDP_ATTR_PROTO_DESC_LIST ,
102
+ BT_SDP_TYPE_SIZE_VAR (BT_SDP_SEQ8 , 12 ),
103
+ BT_SDP_DATA_ELEM_LIST (
104
+ {
105
+ BT_SDP_TYPE_SIZE_VAR (BT_SDP_SEQ8 , 3 ),
106
+ BT_SDP_DATA_ELEM_LIST (
107
+ {
108
+ BT_SDP_TYPE_SIZE (BT_SDP_UUID16 ),
109
+ BT_SDP_ARRAY_16 (BT_SDP_PROTO_L2CAP )
110
+ },
111
+ )
112
+ },
113
+ {
114
+ BT_SDP_TYPE_SIZE_VAR (BT_SDP_SEQ8 , 5 ),
115
+ BT_SDP_DATA_ELEM_LIST (
116
+ {
117
+ BT_SDP_TYPE_SIZE (BT_SDP_UUID16 ),
118
+ BT_SDP_ARRAY_16 (BT_SDP_PROTO_RFCOMM )
119
+ },
120
+ {
121
+ BT_SDP_TYPE_SIZE (BT_SDP_UINT8 ),
122
+ BT_SDP_ARRAY_8 (BT_RFCOMM_CHAN_HFP_AG )
123
+ },
124
+ )
125
+ },
126
+ )
127
+ ),
128
+ BT_SDP_LIST (
129
+ BT_SDP_ATTR_PROFILE_DESC_LIST ,
130
+ BT_SDP_TYPE_SIZE_VAR (BT_SDP_SEQ8 , 6 ),
131
+ BT_SDP_DATA_ELEM_LIST (
132
+ {
133
+ BT_SDP_TYPE_SIZE (BT_SDP_UUID16 ),
134
+ BT_SDP_ARRAY_16 (BT_SDP_HANDSFREE_SVCLASS )
135
+ },
136
+ {
137
+ BT_SDP_TYPE_SIZE (BT_SDP_UINT16 ),
138
+ BT_SDP_ARRAY_16 (0x0109 )
139
+ },
140
+ )
141
+ ),
142
+
143
+ BT_SDP_LIST (
144
+ BT_SDP_ATTR_NETWORK ,
145
+ BT_SDP_TYPE_SIZE (BT_SDP_UINT8 ),
146
+ BT_SDP_ARRAY_8 (IS_ENABLED (CONFIG_BT_HFP_AG_REJECT_CALL ))
147
+ ),
148
+ /* The values of the “SupportedFeatures” bitmap shall be the same as the
149
+ * values of the Bits 0 to 4 of the AT-command AT+BRSF (see Section 5.3).
150
+ */
151
+ BT_SDP_SUPPORTED_FEATURES (BT_HFP_AG_SDP_SUPPORTED_FEATURES ),
152
+ };
153
+
154
+ static struct bt_sdp_record hfp_ag_rec = BT_SDP_RECORD (hfp_ag_attrs );
85
155
86
156
static enum at_cme bt_hfp_ag_get_cme_err (int err )
87
157
{
@@ -3205,6 +3275,8 @@ static void hfp_ag_disconnected(struct bt_rfcomm_dlc *dlc)
3205
3275
}
3206
3276
}
3207
3277
3278
+ ag -> acl_conn = NULL ;
3279
+
3208
3280
LOG_DBG ("AG %p" , ag );
3209
3281
}
3210
3282
@@ -3481,121 +3553,133 @@ static void bt_ag_ringing_work(struct k_work *work)
3481
3553
(void )hfp_ag_next_step (call -> ag , bt_ag_ringing_work_cb , call );
3482
3554
}
3483
3555
3484
- int bt_hfp_ag_connect (struct bt_conn * conn , struct bt_hfp_ag * * ag , uint8_t channel )
3485
- {
3486
- int i ;
3487
- int err ;
3556
+ static K_KERNEL_STACK_MEMBER (ag_thread_stack , CONFIG_BT_HFP_AG_THREAD_STACK_SIZE ) ;
3488
3557
3558
+ static struct bt_hfp_ag * hfp_ag_create (struct bt_conn * conn )
3559
+ {
3489
3560
static struct bt_rfcomm_dlc_ops ops = {
3490
3561
.connected = hfp_ag_connected ,
3491
3562
.disconnected = hfp_ag_disconnected ,
3492
3563
.recv = hfp_ag_recv ,
3493
3564
.sent = hfp_ag_sent ,
3494
3565
};
3566
+ static k_tid_t ag_thread_id ;
3567
+ static struct k_thread ag_thread ;
3568
+ size_t index ;
3569
+ struct bt_hfp_ag * ag ;
3495
3570
3496
- LOG_DBG ("" );
3497
-
3498
- if (ag == NULL ) {
3499
- return - EINVAL ;
3500
- }
3501
-
3502
- * ag = NULL ;
3571
+ LOG_DBG ("conn %p" , conn );
3503
3572
3504
3573
if (ag_thread_id == NULL ) {
3505
3574
3506
3575
k_fifo_init (& ag_tx_free );
3507
3576
k_fifo_init (& ag_tx_notify );
3508
3577
3509
- for (i = 0 ; i < ARRAY_SIZE (ag_tx ); i ++ ) {
3510
- k_fifo_put (& ag_tx_free , & ag_tx [i ]);
3578
+ for (index = 0 ; index < ARRAY_SIZE (ag_tx ); index ++ ) {
3579
+ k_fifo_put (& ag_tx_free , & ag_tx [index ]);
3511
3580
}
3512
3581
3513
3582
ag_thread_id = k_thread_create (
3514
3583
& ag_thread , ag_thread_stack , K_KERNEL_STACK_SIZEOF (ag_thread_stack ),
3515
3584
bt_hfp_ag_thread , NULL , NULL , NULL ,
3516
3585
K_PRIO_COOP (CONFIG_BT_HFP_AG_THREAD_PRIO ), 0 , K_NO_WAIT );
3517
- if (ag_thread_id == NULL ) {
3518
- return - ENOMEM ;
3519
- }
3586
+ __ASSERT (ag_thread_id , "Cannot create thread for AG" );
3520
3587
k_thread_name_set (ag_thread_id , "HFP AG" );
3521
3588
}
3522
3589
3523
- for (i = 0 ; i < ARRAY_SIZE (bt_hfp_ag_pool ); i ++ ) {
3524
- struct bt_hfp_ag * _ag = & bt_hfp_ag_pool [i ];
3590
+ index = (size_t )bt_conn_index (conn );
3591
+ ag = & bt_hfp_ag_pool [index ];
3592
+ if (ag -> acl_conn ) {
3593
+ LOG_ERR ("AG connection (%p) is established" , conn );
3594
+ return NULL ;
3595
+ }
3525
3596
3526
- if (_ag -> rfcomm_dlc .session ) {
3527
- continue ;
3528
- }
3597
+ (void )memset (ag , 0 , sizeof (struct bt_hfp_ag ));
3529
3598
3530
- ( void ) memset ( _ag , 0 , sizeof ( struct bt_hfp_ag ) );
3599
+ sys_slist_init ( & ag -> tx_pending );
3531
3600
3532
- sys_slist_init ( & _ag -> tx_pending );
3601
+ k_sem_init ( & ag -> lock , 1 , 1 );
3533
3602
3534
- k_sem_init (& _ag -> lock , 1 , 1 );
3603
+ ag -> rfcomm_dlc .ops = & ops ;
3604
+ ag -> rfcomm_dlc .mtu = BT_HFP_MAX_MTU ;
3535
3605
3536
- _ag -> rfcomm_dlc . ops = & ops ;
3537
- _ag -> rfcomm_dlc . mtu = BT_HFP_MAX_MTU ;
3606
+ /* Set the supported features*/
3607
+ ag -> ag_features = BT_HFP_AG_SUPPORTED_FEATURES ;
3538
3608
3539
- /* Set the supported features*/
3540
- _ag -> ag_features = BT_HFP_AG_SUPPORTED_FEATURES ;
3609
+ /* Support HF indicators */
3610
+ if (IS_ENABLED (CONFIG_BT_HFP_AG_HF_INDICATOR_ENH_SAFETY )) {
3611
+ ag -> hf_indicators_of_ag |= BIT (HFP_HF_ENHANCED_SAFETY_IND );
3612
+ }
3541
3613
3542
- /* Support HF indicators */
3543
- if (IS_ENABLED (CONFIG_BT_HFP_AG_HF_INDICATOR_ENH_SAFETY )) {
3544
- _ag -> hf_indicators_of_ag |= BIT (HFP_HF_ENHANCED_SAFETY_IND );
3545
- }
3614
+ if (IS_ENABLED (CONFIG_BT_HFP_AG_HF_INDICATOR_BATTERY )) {
3615
+ ag -> hf_indicators_of_ag |= BIT (HFP_HF_BATTERY_LEVEL_IND );
3616
+ }
3546
3617
3547
- if (IS_ENABLED (CONFIG_BT_HFP_AG_HF_INDICATOR_BATTERY )) {
3548
- _ag -> hf_indicators_of_ag |= BIT (HFP_HF_BATTERY_LEVEL_IND );
3549
- }
3618
+ ag -> hf_indicators = ag -> hf_indicators_of_ag ;
3550
3619
3551
- _ag -> hf_indicators = _ag -> hf_indicators_of_ag ;
3620
+ /* If supported codec ids cannot be notified, disable codec negotiation. */
3621
+ if (!(bt_ag && bt_ag -> codec )) {
3622
+ ag -> ag_features &= ~BT_HFP_AG_FEATURE_CODEC_NEG ;
3623
+ }
3552
3624
3553
- /* If supported codec ids cannot be notified, disable codec negotiation. */
3554
- if (!(bt_ag && bt_ag -> codec )) {
3555
- _ag -> ag_features &= ~BT_HFP_AG_FEATURE_CODEC_NEG ;
3556
- }
3625
+ ag -> hf_features = 0 ;
3626
+ ag -> hf_codec_ids = 0 ;
3627
+
3628
+ ag -> acl_conn = conn ;
3629
+
3630
+ /* Set AG indicator value */
3631
+ ag -> indicator_value [BT_HFP_AG_SERVICE_IND ] = 0 ;
3632
+ ag -> indicator_value [BT_HFP_AG_CALL_IND ] = 0 ;
3633
+ ag -> indicator_value [BT_HFP_AG_CALL_SETUP_IND ] = 0 ;
3634
+ ag -> indicator_value [BT_HFP_AG_CALL_HELD_IND ] = 0 ;
3635
+ ag -> indicator_value [BT_HFP_AG_SIGNAL_IND ] = 0 ;
3636
+ ag -> indicator_value [BT_HFP_AG_ROAM_IND ] = 0 ;
3637
+ ag -> indicator_value [BT_HFP_AG_BATTERY_IND ] = 0 ;
3638
+
3639
+ /* Set AG indicator status */
3640
+ ag -> indicator = BIT (BT_HFP_AG_SERVICE_IND ) | BIT (BT_HFP_AG_CALL_IND ) |
3641
+ BIT (BT_HFP_AG_CALL_SETUP_IND ) | BIT (BT_HFP_AG_CALL_HELD_IND ) |
3642
+ BIT (BT_HFP_AG_SIGNAL_IND ) | BIT (BT_HFP_AG_ROAM_IND ) |
3643
+ BIT (BT_HFP_AG_BATTERY_IND );
3557
3644
3558
- _ag -> hf_features = 0 ;
3559
- _ag -> hf_codec_ids = 0 ;
3645
+ /* Set AG operator */
3646
+ memcpy ( ag -> operator , "UNKNOWN" , sizeof ( "UNKNOWN" )) ;
3560
3647
3561
- _ag -> acl_conn = conn ;
3648
+ /* Set Codec ID*/
3649
+ ag -> selected_codec_id = BT_HFP_AG_CODEC_CVSD ;
3562
3650
3563
- /* Set AG indicator value */
3564
- _ag -> indicator_value [BT_HFP_AG_SERVICE_IND ] = 0 ;
3565
- _ag -> indicator_value [BT_HFP_AG_CALL_IND ] = 0 ;
3566
- _ag -> indicator_value [BT_HFP_AG_CALL_SETUP_IND ] = 0 ;
3567
- _ag -> indicator_value [BT_HFP_AG_CALL_HELD_IND ] = 0 ;
3568
- _ag -> indicator_value [BT_HFP_AG_SIGNAL_IND ] = 0 ;
3569
- _ag -> indicator_value [BT_HFP_AG_ROAM_IND ] = 0 ;
3570
- _ag -> indicator_value [BT_HFP_AG_BATTERY_IND ] = 0 ;
3651
+ /* Init delay work */
3652
+ k_work_init_delayable (& ag -> tx_work , bt_ag_tx_work );
3571
3653
3572
- /* Set AG indicator status */
3573
- _ag -> indicator = BIT (BT_HFP_AG_SERVICE_IND ) | BIT (BT_HFP_AG_CALL_IND ) |
3574
- BIT (BT_HFP_AG_CALL_SETUP_IND ) | BIT (BT_HFP_AG_CALL_HELD_IND ) |
3575
- BIT (BT_HFP_AG_SIGNAL_IND ) | BIT (BT_HFP_AG_ROAM_IND ) |
3576
- BIT (BT_HFP_AG_BATTERY_IND );
3654
+ return ag ;
3655
+ }
3577
3656
3578
- /* Set AG operator */
3579
- memcpy (_ag -> operator , "UNKNOWN" , sizeof ("UNKNOWN" ));
3657
+ int bt_hfp_ag_connect (struct bt_conn * conn , struct bt_hfp_ag * * ag , uint8_t channel )
3658
+ {
3659
+ struct bt_hfp_ag * new_ag ;
3660
+ int err ;
3580
3661
3581
- /* Set Codec ID*/
3582
- _ag -> selected_codec_id = BT_HFP_AG_CODEC_CVSD ;
3662
+ LOG_DBG ("" );
3583
3663
3584
- /* Init delay work */
3585
- k_work_init_delayable (& _ag -> tx_work , bt_ag_tx_work );
3664
+ if (!conn || !ag || !channel ) {
3665
+ return - EINVAL ;
3666
+ }
3586
3667
3587
- * ag = _ag ;
3668
+ if (!bt_ag ) {
3669
+ return - EFAULT ;
3588
3670
}
3589
3671
3590
- if (* ag == NULL ) {
3591
- return - ENOMEM ;
3672
+ new_ag = hfp_ag_create (conn );
3673
+ if (!new_ag ) {
3674
+ return - ECONNREFUSED ;
3592
3675
}
3593
3676
3594
- err = bt_rfcomm_dlc_connect (conn , & ( * ag ) -> rfcomm_dlc , channel );
3677
+ err = bt_rfcomm_dlc_connect (conn , & new_ag -> rfcomm_dlc , channel );
3595
3678
if (err != 0 ) {
3596
- (void )memset (* ag , 0 , sizeof (struct bt_hfp_ag ));
3679
+ (void )memset (new_ag , 0 , sizeof (* new_ag ));
3597
3680
* ag = NULL ;
3598
3681
} else {
3682
+ * ag = new_ag ;
3599
3683
bt_hfp_ag_set_state (* ag , BT_HFP_CONNECTING );
3600
3684
}
3601
3685
@@ -3615,6 +3699,71 @@ int bt_hfp_ag_disconnect(struct bt_hfp_ag *ag)
3615
3699
return bt_rfcomm_dlc_disconnect (& ag -> rfcomm_dlc );
3616
3700
}
3617
3701
3702
+ static int hfp_ag_accept (struct bt_conn * conn , struct bt_rfcomm_server * server ,
3703
+ struct bt_rfcomm_dlc * * dlc )
3704
+ {
3705
+ struct bt_hfp_ag * ag ;
3706
+
3707
+ ag = hfp_ag_create (conn );
3708
+
3709
+ if (!ag ) {
3710
+ return - ECONNREFUSED ;
3711
+ }
3712
+
3713
+ * dlc = & ag -> rfcomm_dlc ;
3714
+
3715
+ return 0 ;
3716
+ }
3717
+
3718
+ static int bt_hfp_ag_sco_accept (const struct bt_sco_accept_info * info ,
3719
+ struct bt_sco_chan * * chan )
3720
+ {
3721
+ static struct bt_sco_chan_ops ops = {
3722
+ .connected = hfp_ag_sco_connected ,
3723
+ .disconnected = hfp_ag_sco_disconnected ,
3724
+ };
3725
+ size_t index ;
3726
+ struct bt_hfp_ag * ag ;
3727
+
3728
+ LOG_DBG ("conn %p" , info -> acl );
3729
+
3730
+ index = (size_t )bt_conn_index (info -> acl );
3731
+ ag = & bt_hfp_ag_pool [index ];
3732
+ if (ag -> acl_conn != info -> acl ) {
3733
+ LOG_ERR ("ACL %p of AG is unaligned with SCO's %p" , ag -> acl_conn , info -> acl );
3734
+ return - EINVAL ;
3735
+ }
3736
+
3737
+ if (ag -> sco_chan .sco ) {
3738
+ return - ECONNREFUSED ;
3739
+ }
3740
+
3741
+ ag -> sco_chan .ops = & ops ;
3742
+
3743
+ * chan = & ag -> sco_chan ;
3744
+
3745
+ return 0 ;
3746
+ }
3747
+
3748
+ static void hfp_ag_init (void )
3749
+ {
3750
+ static struct bt_rfcomm_server chan = {
3751
+ .channel = BT_RFCOMM_CHAN_HFP_AG ,
3752
+ .accept = hfp_ag_accept ,
3753
+ };
3754
+
3755
+ bt_rfcomm_server_register (& chan );
3756
+
3757
+ static struct bt_sco_server sco_server = {
3758
+ .sec_level = BT_SECURITY_L0 ,
3759
+ .accept = bt_hfp_ag_sco_accept ,
3760
+ };
3761
+
3762
+ bt_sco_server_register (& sco_server );
3763
+
3764
+ bt_sdp_register_service (& hfp_ag_rec );
3765
+ }
3766
+
3618
3767
int bt_hfp_ag_register (struct bt_hfp_ag_cb * cb )
3619
3768
{
3620
3769
if (!cb ) {
@@ -3627,6 +3776,8 @@ int bt_hfp_ag_register(struct bt_hfp_ag_cb *cb)
3627
3776
3628
3777
bt_ag = cb ;
3629
3778
3779
+ hfp_ag_init ();
3780
+
3630
3781
return 0 ;
3631
3782
}
3632
3783
0 commit comments