@ -4006,6 +4006,79 @@ unlock:
return err ;
}
static int set_secure_conn ( struct sock * sk , struct hci_dev * hdev ,
void * data , u16 len )
{
struct mgmt_mode * cp = data ;
struct pending_cmd * cmd ;
u8 status ;
int err ;
BT_DBG ( " request for %s " , hdev - > name ) ;
status = mgmt_bredr_support ( hdev ) ;
if ( status )
return cmd_status ( sk , hdev - > id , MGMT_OP_SET_SECURE_CONN ,
status ) ;
if ( ! lmp_sc_capable ( hdev ) )
return cmd_status ( sk , hdev - > id , MGMT_OP_SET_SECURE_CONN ,
MGMT_STATUS_NOT_SUPPORTED ) ;
if ( cp - > val ! = 0x00 & & cp - > val ! = 0x01 )
return cmd_status ( sk , hdev - > id , MGMT_OP_SET_SECURE_CONN ,
MGMT_STATUS_INVALID_PARAMS ) ;
hci_dev_lock ( hdev ) ;
if ( ! hdev_is_powered ( hdev ) ) {
bool changed ;
if ( cp - > val )
changed = ! test_and_set_bit ( HCI_SC_ENABLED ,
& hdev - > dev_flags ) ;
else
changed = test_and_clear_bit ( HCI_SC_ENABLED ,
& hdev - > dev_flags ) ;
err = send_settings_rsp ( sk , MGMT_OP_SET_SECURE_CONN , hdev ) ;
if ( err < 0 )
goto failed ;
if ( changed )
err = new_settings ( hdev , sk ) ;
goto failed ;
}
if ( mgmt_pending_find ( MGMT_OP_SET_SECURE_CONN , hdev ) ) {
err = cmd_status ( sk , hdev - > id , MGMT_OP_SET_SECURE_CONN ,
MGMT_STATUS_BUSY ) ;
goto failed ;
}
if ( ! ! cp - > val = = test_bit ( HCI_SC_ENABLED , & hdev - > dev_flags ) ) {
err = send_settings_rsp ( sk , MGMT_OP_SET_SECURE_CONN , hdev ) ;
goto failed ;
}
cmd = mgmt_pending_add ( sk , MGMT_OP_SET_SECURE_CONN , hdev , data , len ) ;
if ( ! cmd ) {
err = - ENOMEM ;
goto failed ;
}
err = hci_send_cmd ( hdev , HCI_OP_WRITE_SC_SUPPORT , 1 , & cp - > val ) ;
if ( err < 0 ) {
mgmt_pending_remove ( cmd ) ;
goto failed ;
}
failed :
hci_dev_unlock ( hdev ) ;
return err ;
}
static bool ltk_is_valid ( struct mgmt_ltk_info * key )
{
if ( key - > authenticated ! = 0x00 & & key - > authenticated ! = 0x01 )
@ -4134,6 +4207,7 @@ static const struct mgmt_handler {
{ set_bredr , false , MGMT_SETTING_SIZE } ,
{ set_static_address , false , MGMT_SET_STATIC_ADDRESS_SIZE } ,
{ set_scan_params , false , MGMT_SET_SCAN_PARAMS_SIZE } ,
{ set_secure_conn , false , MGMT_SETTING_SIZE } ,
} ;
@ -4917,6 +4991,38 @@ void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
hci_req_run ( & req , NULL ) ;
}
void mgmt_sc_enable_complete ( struct hci_dev * hdev , u8 enable , u8 status )
{
struct cmd_lookup match = { NULL , hdev } ;
bool changed = false ;
if ( status ) {
u8 mgmt_err = mgmt_status ( status ) ;
if ( enable & & test_and_clear_bit ( HCI_SC_ENABLED ,
& hdev - > dev_flags ) )
new_settings ( hdev , NULL ) ;
mgmt_pending_foreach ( MGMT_OP_SET_SECURE_CONN , hdev ,
cmd_status_rsp , & mgmt_err ) ;
return ;
}
if ( enable )
changed = ! test_and_set_bit ( HCI_SC_ENABLED , & hdev - > dev_flags ) ;
else
changed = test_and_clear_bit ( HCI_SC_ENABLED , & hdev - > dev_flags ) ;
mgmt_pending_foreach ( MGMT_OP_SET_SECURE_CONN , hdev ,
settings_rsp , & match ) ;
if ( changed )
new_settings ( hdev , match . sk ) ;
if ( match . sk )
sock_put ( match . sk ) ;
}
static void sk_lookup ( struct pending_cmd * cmd , void * data )
{
struct cmd_lookup * match = data ;