@@ -3882,7 +3882,7 @@ static const u8 offload_codecs_uuid[16] = {
3882
3882
};
3883
3883
3884
3884
/* 671b10b5-42c0-4696-9227-eb28d1b049d6 */
3885
- static const u8 simult_central_periph_uuid [16 ] = {
3885
+ static const u8 le_simultaneous_roles_uuid [16 ] = {
3886
3886
0xd6 , 0x49 , 0xb0 , 0xd1 , 0x28 , 0xeb , 0x27 , 0x92 ,
3887
3887
0x96 , 0x46 , 0xc0 , 0x42 , 0xb5 , 0x10 , 0x1b , 0x67 ,
3888
3888
};
@@ -3915,13 +3915,13 @@ static int read_exp_features_info(struct sock *sk, struct hci_dev *hdev,
3915
3915
}
3916
3916
#endif
3917
3917
3918
- if (hdev ) {
3919
- if (hci_dev_le_state_simultaneous (hdev ))
3918
+ if (hdev && hci_dev_le_state_simultaneous ( hdev ) ) {
3919
+ if (hci_dev_test_flag (hdev , HCI_LE_SIMULTANEOUS_ROLES ))
3920
3920
flags = BIT (0 );
3921
3921
else
3922
3922
flags = 0 ;
3923
3923
3924
- memcpy (rp -> features [idx ].uuid , simult_central_periph_uuid , 16 );
3924
+ memcpy (rp -> features [idx ].uuid , le_simultaneous_roles_uuid , 16 );
3925
3925
rp -> features [idx ].flags = cpu_to_le32 (flags );
3926
3926
idx ++ ;
3927
3927
}
@@ -3992,29 +3992,13 @@ static int exp_ll_privacy_feature_changed(bool enabled, struct hci_dev *hdev,
3992
3992
3993
3993
}
3994
3994
3995
- #ifdef CONFIG_BT_FEATURE_DEBUG
3996
- static int exp_debug_feature_changed (bool enabled , struct sock * skip )
3997
- {
3998
- struct mgmt_ev_exp_feature_changed ev ;
3999
-
4000
- memset (& ev , 0 , sizeof (ev ));
4001
- memcpy (ev .uuid , debug_uuid , 16 );
4002
- ev .flags = cpu_to_le32 (enabled ? BIT (0 ) : 0 );
4003
-
4004
- return mgmt_limited_event (MGMT_EV_EXP_FEATURE_CHANGED , NULL ,
4005
- & ev , sizeof (ev ),
4006
- HCI_MGMT_EXP_FEATURE_EVENTS , skip );
4007
- }
4008
- #endif
4009
-
4010
- static int exp_quality_report_feature_changed (bool enabled ,
4011
- struct hci_dev * hdev ,
4012
- struct sock * skip )
3995
+ static int exp_feature_changed (struct hci_dev * hdev , const u8 * uuid ,
3996
+ bool enabled , struct sock * skip )
4013
3997
{
4014
3998
struct mgmt_ev_exp_feature_changed ev ;
4015
3999
4016
4000
memset (& ev , 0 , sizeof (ev ));
4017
- memcpy (ev .uuid , quality_report_uuid , 16 );
4001
+ memcpy (ev .uuid , uuid , 16 );
4018
4002
ev .flags = cpu_to_le32 (enabled ? BIT (0 ) : 0 );
4019
4003
4020
4004
return mgmt_limited_event (MGMT_EV_EXP_FEATURE_CHANGED , hdev ,
@@ -4044,7 +4028,7 @@ static int set_zero_key_func(struct sock *sk, struct hci_dev *hdev,
4044
4028
bt_dbg_set (false);
4045
4029
4046
4030
if (changed )
4047
- exp_debug_feature_changed ( false, sk );
4031
+ exp_feature_changed ( NULL , ZERO_KEY , false, sk );
4048
4032
}
4049
4033
#endif
4050
4034
@@ -4054,7 +4038,8 @@ static int set_zero_key_func(struct sock *sk, struct hci_dev *hdev,
4054
4038
changed = hci_dev_test_and_clear_flag (hdev ,
4055
4039
HCI_ENABLE_LL_PRIVACY );
4056
4040
if (changed )
4057
- exp_ll_privacy_feature_changed (false, hdev , sk );
4041
+ exp_feature_changed (hdev , rpa_resolution_uuid , false,
4042
+ sk );
4058
4043
}
4059
4044
4060
4045
hci_sock_set_flag (sk , HCI_MGMT_EXP_FEATURE_EVENTS );
@@ -4105,7 +4090,7 @@ static int set_debug_func(struct sock *sk, struct hci_dev *hdev,
4105
4090
& rp , sizeof (rp ));
4106
4091
4107
4092
if (changed )
4108
- exp_debug_feature_changed ( val , sk );
4093
+ exp_feature_changed ( hdev , debug_uuid , val , sk );
4109
4094
4110
4095
return err ;
4111
4096
}
@@ -4243,27 +4228,13 @@ static int set_quality_report_func(struct sock *sk, struct hci_dev *hdev,
4243
4228
& rp , sizeof (rp ));
4244
4229
4245
4230
if (changed )
4246
- exp_quality_report_feature_changed ( val , hdev , sk );
4231
+ exp_feature_changed ( hdev , quality_report_uuid , val , sk );
4247
4232
4248
4233
unlock_quality_report :
4249
4234
hci_req_sync_unlock (hdev );
4250
4235
return err ;
4251
4236
}
4252
4237
4253
- static int exp_offload_codec_feature_changed (bool enabled , struct hci_dev * hdev ,
4254
- struct sock * skip )
4255
- {
4256
- struct mgmt_ev_exp_feature_changed ev ;
4257
-
4258
- memset (& ev , 0 , sizeof (ev ));
4259
- memcpy (ev .uuid , offload_codecs_uuid , 16 );
4260
- ev .flags = cpu_to_le32 (enabled ? BIT (0 ) : 0 );
4261
-
4262
- return mgmt_limited_event (MGMT_EV_EXP_FEATURE_CHANGED , hdev ,
4263
- & ev , sizeof (ev ),
4264
- HCI_MGMT_EXP_FEATURE_EVENTS , skip );
4265
- }
4266
-
4267
4238
static int set_offload_codec_func (struct sock * sk , struct hci_dev * hdev ,
4268
4239
struct mgmt_cp_set_exp_feature * cp ,
4269
4240
u16 data_len )
@@ -4317,7 +4288,65 @@ static int set_offload_codec_func(struct sock *sk, struct hci_dev *hdev,
4317
4288
& rp , sizeof (rp ));
4318
4289
4319
4290
if (changed )
4320
- exp_offload_codec_feature_changed (val , hdev , sk );
4291
+ exp_feature_changed (hdev , offload_codecs_uuid , val , sk );
4292
+
4293
+ return err ;
4294
+ }
4295
+
4296
+ static int set_le_simultaneous_roles_func (struct sock * sk , struct hci_dev * hdev ,
4297
+ struct mgmt_cp_set_exp_feature * cp ,
4298
+ u16 data_len )
4299
+ {
4300
+ bool val , changed ;
4301
+ int err ;
4302
+ struct mgmt_rp_set_exp_feature rp ;
4303
+
4304
+ /* Command requires to use a valid controller index */
4305
+ if (!hdev )
4306
+ return mgmt_cmd_status (sk , MGMT_INDEX_NONE ,
4307
+ MGMT_OP_SET_EXP_FEATURE ,
4308
+ MGMT_STATUS_INVALID_INDEX );
4309
+
4310
+ /* Parameters are limited to a single octet */
4311
+ if (data_len != MGMT_SET_EXP_FEATURE_SIZE + 1 )
4312
+ return mgmt_cmd_status (sk , hdev -> id ,
4313
+ MGMT_OP_SET_EXP_FEATURE ,
4314
+ MGMT_STATUS_INVALID_PARAMS );
4315
+
4316
+ /* Only boolean on/off is supported */
4317
+ if (cp -> param [0 ] != 0x00 && cp -> param [0 ] != 0x01 )
4318
+ return mgmt_cmd_status (sk , hdev -> id ,
4319
+ MGMT_OP_SET_EXP_FEATURE ,
4320
+ MGMT_STATUS_INVALID_PARAMS );
4321
+
4322
+ val = !!cp -> param [0 ];
4323
+ changed = (val != hci_dev_test_flag (hdev , HCI_LE_SIMULTANEOUS_ROLES ));
4324
+
4325
+ if (!hci_dev_le_state_simultaneous (hdev )) {
4326
+ return mgmt_cmd_status (sk , hdev -> id ,
4327
+ MGMT_OP_SET_EXP_FEATURE ,
4328
+ MGMT_STATUS_NOT_SUPPORTED );
4329
+ }
4330
+
4331
+ if (changed ) {
4332
+ if (val )
4333
+ hci_dev_set_flag (hdev , HCI_LE_SIMULTANEOUS_ROLES );
4334
+ else
4335
+ hci_dev_clear_flag (hdev , HCI_LE_SIMULTANEOUS_ROLES );
4336
+ }
4337
+
4338
+ bt_dev_info (hdev , "LE simultanous roles enable %d changed %d" ,
4339
+ val , changed );
4340
+
4341
+ memcpy (rp .uuid , le_simultaneous_roles_uuid , 16 );
4342
+ rp .flags = cpu_to_le32 (val ? BIT (0 ) : 0 );
4343
+ hci_sock_set_flag (sk , HCI_MGMT_EXP_FEATURE_EVENTS );
4344
+ err = mgmt_cmd_complete (sk , hdev -> id ,
4345
+ MGMT_OP_SET_EXP_FEATURE , 0 ,
4346
+ & rp , sizeof (rp ));
4347
+
4348
+ if (changed )
4349
+ exp_feature_changed (hdev , le_simultaneous_roles_uuid , val , sk );
4321
4350
4322
4351
return err ;
4323
4352
}
@@ -4334,6 +4363,7 @@ static const struct mgmt_exp_feature {
4334
4363
EXP_FEAT (rpa_resolution_uuid , set_rpa_resolution_func ),
4335
4364
EXP_FEAT (quality_report_uuid , set_quality_report_func ),
4336
4365
EXP_FEAT (offload_codecs_uuid , set_offload_codec_func ),
4366
+ EXP_FEAT (le_simultaneous_roles_uuid , set_le_simultaneous_roles_func ),
4337
4367
4338
4368
/* end with a null feature */
4339
4369
EXP_FEAT (NULL , NULL )
0 commit comments