2021-10-28 02:58:38 +03:00
// SPDX-License-Identifier: GPL-2.0
/*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright ( C ) 2021 Intel Corporation
*/
# include <net/bluetooth/bluetooth.h>
# include <net/bluetooth/hci_core.h>
# include <net/bluetooth/mgmt.h>
# include "hci_request.h"
# include "smp.h"
Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 1
This make use of hci_cmd_sync_queue for the following MGMT commands:
Set Device Class
Set Device ID
Add UUID
Remove UUID
tools/mgmt-tester -s "Set Device Class"
Test Summary
------------
Set Device Class - Success 1 Passed
Set Device Class - Success 2 Passed
Set Device Class - Invalid parameters 1 Passed
Total: 3, Passed: 3 (100.0%), Failed: 0, Not Run: 0
Overall execution time: 0.0599 seconds
tools/mgmt-tester -s "Set Device ID"
Test Summary
------------
Set Device ID - Success 1 Passed
Set Device ID - Success 2 Passed
Set Device ID - Disable Passed
Set Device ID - Power off and Power on Passed
Set Device ID - SSP off and Power on Passed
Set Device ID - Invalid Parameter Passed
Total: 6, Passed: 6 (100.0%), Failed: 0, Not Run: 0
Overall execution time: 0.107 seconds
tools/mgmt-tester -s "Add UUID"
Test Summary
------------
Add UUID - UUID-16 1 Passed
Add UUID - UUID-16 multiple 1 Passed
Add UUID - UUID-16 partial 1 Passed
Add UUID - UUID-32 1 Passed
Add UUID - UUID-32 multiple 1 Passed
Add UUID - UUID-32 partial 1 Passed
Add UUID - UUID-128 1 Passed
Add UUID - UUID-128 multiple 1 Passed
Add UUID - UUID-128 partial 1 Passed
Add UUID - UUID mix Passed
Total: 10, Passed: 10 (100.0%), Failed: 0, Not Run: 0
Overall execution time: 0.198 seconds
tools/mgmt-tester -s "Remove UUID"
Test Summary
------------
Remove UUID - Success 1 Passed
Remove UUID - All UUID - Success 2 Passed
Remove UUID - Power Off - Success 3 Passed
Remove UUID - Power Off and On - Success 4 Passed
Remove UUID - Not Exist - Invalid Params 1 Passed
Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0
Overall execution time: 0.0908 seconds
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-28 02:58:39 +03:00
# include "eir.h"
2021-10-28 02:58:38 +03:00
static void hci_cmd_sync_complete ( struct hci_dev * hdev , u8 result , u16 opcode ,
struct sk_buff * skb )
{
bt_dev_dbg ( hdev , " result 0x%2.2x " , result ) ;
if ( hdev - > req_status ! = HCI_REQ_PEND )
return ;
hdev - > req_result = result ;
hdev - > req_status = HCI_REQ_DONE ;
Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 2
This make use of hci_cmd_sync_queue for the following MGMT commands:
Add Advertising
Remove Advertising
Add Extended Advertising Parameters
Add Extended Advertising Data
mgmt-tester -s "Add Advertising"
Test Summary
------------
Add Advertising - Failure: LE off Passed
Add Advertising - Invalid Params 1 (AD too long) Passed
Add Advertising - Invalid Params 2 (Malformed len) Passed
Add Advertising - Invalid Params 3 (Malformed len) Passed
Add Advertising - Invalid Params 4 (Malformed len) Passed
Add Advertising - Invalid Params 5 (AD too long) Passed
Add Advertising - Invalid Params 6 (ScRsp too long) Passed
Add Advertising - Invalid Params 7 (Malformed len) Passed
Add Advertising - Invalid Params 8 (Malformed len) Passed
Add Advertising - Invalid Params 9 (Malformed len) Passed
Add Advertising - Invalid Params 10 (ScRsp too long) Passed
Add Advertising - Rejected (Timeout, !Powered) Passed
Add Advertising - Success 1 (Powered, Add Adv Inst) Passed
Add Advertising - Success 2 (!Powered, Add Adv Inst) Passed
Add Advertising - Success 3 (!Powered, Adv Enable) Passed
Add Advertising - Success 4 (Set Adv on override) Passed
Add Advertising - Success 5 (Set Adv off override) Passed
Add Advertising - Success 6 (Scan Rsp Dta, Adv ok) Passed
Add Advertising - Success 7 (Scan Rsp Dta, Scan ok) Passed
Add Advertising - Success 8 (Connectable Flag) Passed
Add Advertising - Success 9 (General Discov Flag) Passed
Add Advertising - Success 10 (Limited Discov Flag) Passed
Add Advertising - Success 11 (Managed Flags) Passed
Add Advertising - Success 12 (TX Power Flag) Passed
Add Advertising - Success 13 (ADV_SCAN_IND) Passed
Add Advertising - Success 14 (ADV_NONCONN_IND) Passed
Add Advertising - Success 15 (ADV_IND) Passed
Add Advertising - Success 16 (Connectable -> on) Passed
Add Advertising - Success 17 (Connectable -> off) Passed
Add Advertising - Success 18 (Power -> off, Remove) Passed
Add Advertising - Success 19 (Power -> off, Keep) Passed
Add Advertising - Success 20 (Add Adv override) Passed
Add Advertising - Success 21 (Timeout expires) Passed
Add Advertising - Success 22 (LE -> off, Remove) Passed
Add Advertising - Success (Empty ScRsp) Passed
Add Advertising - Success (ScRsp only) Passed
Add Advertising - Invalid Params (ScRsp too long) Passed
Add Advertising - Success (ScRsp appear) Passed
Add Advertising - Invalid Params (ScRsp appear long) Passed
Add Advertising - Success (Appear is null) Passed
Add Advertising - Success (Name is null) Passed
Add Advertising - Success (Complete name) Passed
Add Advertising - Success (Shortened name) Passed
Add Advertising - Success (Short name) Passed
Add Advertising - Success (Name + data) Passed
Add Advertising - Invalid Params (Name + data) Passed
Add Advertising - Success (Name+data+appear) Passed
Total: 47, Passed: 47 (100.0%), Failed: 0, Not Run: 0
Overall execution time: 2.17 seconds
mgmt-tester -s "Remove Advertising"
Test Summary
------------
Remove Advertising - Invalid Params 1 Passed
Remove Advertising - Success 1 Passed
Remove Advertising - Success 2 Passed
Total: 3, Passed: 3 (100.0%), Failed: 0, Not Run: 0
Overall execution time: 0.0585 seconds
mgmt-tester -s "Ext Adv MGMT Params"
Test Summary:
------------
Ext Adv MGMT Params - Unpowered Passed
Ext Adv MGMT Params - Invalid parameters Passed
Ext Adv MGMT Params - Success Passed
Ext Adv MGMT Params - (5.0) Success Passed
Total: 4, Passed: 4 (100.0%), Failed: 0, Not Run: 0
Overall execution time: 0.0746 seconds
mgmt-tester -s "Ext Adv MGMT -"
Test Summary
------------
Ext Adv MGMT - Data set without Params Passed
Ext Adv MGMT - AD Data (5.0) Invalid parameters Passed
Ext Adv MGMT - AD Data (5.0) Success Passed
Ext Adv MGMT - AD Scan Response (5.0) Success Passed
Total: 4, Passed: 4 (100.0%), Failed: 0, Not Run: 0
Overall execution time: 0.0805 seconds
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-28 02:58:40 +03:00
if ( skb ) {
struct sock * sk = hci_skb_sk ( skb ) ;
/* Drop sk reference if set */
if ( sk )
sock_put ( sk ) ;
hdev - > req_skb = skb_get ( skb ) ;
}
2021-10-28 02:58:38 +03:00
wake_up_interruptible ( & hdev - > req_wait_q ) ;
}
static struct sk_buff * hci_cmd_sync_alloc ( struct hci_dev * hdev , u16 opcode ,
u32 plen , const void * param ,
struct sock * sk )
{
int len = HCI_COMMAND_HDR_SIZE + plen ;
struct hci_command_hdr * hdr ;
struct sk_buff * skb ;
skb = bt_skb_alloc ( len , GFP_ATOMIC ) ;
if ( ! skb )
return NULL ;
hdr = skb_put ( skb , HCI_COMMAND_HDR_SIZE ) ;
hdr - > opcode = cpu_to_le16 ( opcode ) ;
hdr - > plen = plen ;
if ( plen )
skb_put_data ( skb , param , plen ) ;
bt_dev_dbg ( hdev , " skb len %d " , skb - > len ) ;
hci_skb_pkt_type ( skb ) = HCI_COMMAND_PKT ;
hci_skb_opcode ( skb ) = opcode ;
Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 2
This make use of hci_cmd_sync_queue for the following MGMT commands:
Add Advertising
Remove Advertising
Add Extended Advertising Parameters
Add Extended Advertising Data
mgmt-tester -s "Add Advertising"
Test Summary
------------
Add Advertising - Failure: LE off Passed
Add Advertising - Invalid Params 1 (AD too long) Passed
Add Advertising - Invalid Params 2 (Malformed len) Passed
Add Advertising - Invalid Params 3 (Malformed len) Passed
Add Advertising - Invalid Params 4 (Malformed len) Passed
Add Advertising - Invalid Params 5 (AD too long) Passed
Add Advertising - Invalid Params 6 (ScRsp too long) Passed
Add Advertising - Invalid Params 7 (Malformed len) Passed
Add Advertising - Invalid Params 8 (Malformed len) Passed
Add Advertising - Invalid Params 9 (Malformed len) Passed
Add Advertising - Invalid Params 10 (ScRsp too long) Passed
Add Advertising - Rejected (Timeout, !Powered) Passed
Add Advertising - Success 1 (Powered, Add Adv Inst) Passed
Add Advertising - Success 2 (!Powered, Add Adv Inst) Passed
Add Advertising - Success 3 (!Powered, Adv Enable) Passed
Add Advertising - Success 4 (Set Adv on override) Passed
Add Advertising - Success 5 (Set Adv off override) Passed
Add Advertising - Success 6 (Scan Rsp Dta, Adv ok) Passed
Add Advertising - Success 7 (Scan Rsp Dta, Scan ok) Passed
Add Advertising - Success 8 (Connectable Flag) Passed
Add Advertising - Success 9 (General Discov Flag) Passed
Add Advertising - Success 10 (Limited Discov Flag) Passed
Add Advertising - Success 11 (Managed Flags) Passed
Add Advertising - Success 12 (TX Power Flag) Passed
Add Advertising - Success 13 (ADV_SCAN_IND) Passed
Add Advertising - Success 14 (ADV_NONCONN_IND) Passed
Add Advertising - Success 15 (ADV_IND) Passed
Add Advertising - Success 16 (Connectable -> on) Passed
Add Advertising - Success 17 (Connectable -> off) Passed
Add Advertising - Success 18 (Power -> off, Remove) Passed
Add Advertising - Success 19 (Power -> off, Keep) Passed
Add Advertising - Success 20 (Add Adv override) Passed
Add Advertising - Success 21 (Timeout expires) Passed
Add Advertising - Success 22 (LE -> off, Remove) Passed
Add Advertising - Success (Empty ScRsp) Passed
Add Advertising - Success (ScRsp only) Passed
Add Advertising - Invalid Params (ScRsp too long) Passed
Add Advertising - Success (ScRsp appear) Passed
Add Advertising - Invalid Params (ScRsp appear long) Passed
Add Advertising - Success (Appear is null) Passed
Add Advertising - Success (Name is null) Passed
Add Advertising - Success (Complete name) Passed
Add Advertising - Success (Shortened name) Passed
Add Advertising - Success (Short name) Passed
Add Advertising - Success (Name + data) Passed
Add Advertising - Invalid Params (Name + data) Passed
Add Advertising - Success (Name+data+appear) Passed
Total: 47, Passed: 47 (100.0%), Failed: 0, Not Run: 0
Overall execution time: 2.17 seconds
mgmt-tester -s "Remove Advertising"
Test Summary
------------
Remove Advertising - Invalid Params 1 Passed
Remove Advertising - Success 1 Passed
Remove Advertising - Success 2 Passed
Total: 3, Passed: 3 (100.0%), Failed: 0, Not Run: 0
Overall execution time: 0.0585 seconds
mgmt-tester -s "Ext Adv MGMT Params"
Test Summary:
------------
Ext Adv MGMT Params - Unpowered Passed
Ext Adv MGMT Params - Invalid parameters Passed
Ext Adv MGMT Params - Success Passed
Ext Adv MGMT Params - (5.0) Success Passed
Total: 4, Passed: 4 (100.0%), Failed: 0, Not Run: 0
Overall execution time: 0.0746 seconds
mgmt-tester -s "Ext Adv MGMT -"
Test Summary
------------
Ext Adv MGMT - Data set without Params Passed
Ext Adv MGMT - AD Data (5.0) Invalid parameters Passed
Ext Adv MGMT - AD Data (5.0) Success Passed
Ext Adv MGMT - AD Scan Response (5.0) Success Passed
Total: 4, Passed: 4 (100.0%), Failed: 0, Not Run: 0
Overall execution time: 0.0805 seconds
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-28 02:58:40 +03:00
/* Grab a reference if command needs to be associated with a sock (e.g.
* likely mgmt socket that initiated the command ) .
*/
if ( sk ) {
hci_skb_sk ( skb ) = sk ;
sock_hold ( sk ) ;
}
2021-10-28 02:58:38 +03:00
return skb ;
}
static void hci_cmd_sync_add ( struct hci_request * req , u16 opcode , u32 plen ,
const void * param , u8 event , struct sock * sk )
{
struct hci_dev * hdev = req - > hdev ;
struct sk_buff * skb ;
bt_dev_dbg ( hdev , " opcode 0x%4.4x plen %d " , opcode , plen ) ;
/* If an error occurred during request building, there is no point in
* queueing the HCI command . We can simply return .
*/
if ( req - > err )
return ;
skb = hci_cmd_sync_alloc ( hdev , opcode , plen , param , sk ) ;
if ( ! skb ) {
bt_dev_err ( hdev , " no memory for command (opcode 0x%4.4x) " ,
opcode ) ;
req - > err = - ENOMEM ;
return ;
}
if ( skb_queue_empty ( & req - > cmd_q ) )
bt_cb ( skb ) - > hci . req_flags | = HCI_REQ_START ;
bt_cb ( skb ) - > hci . req_event = event ;
skb_queue_tail ( & req - > cmd_q , skb ) ;
}
static int hci_cmd_sync_run ( struct hci_request * req )
{
struct hci_dev * hdev = req - > hdev ;
struct sk_buff * skb ;
unsigned long flags ;
bt_dev_dbg ( hdev , " length %u " , skb_queue_len ( & req - > cmd_q ) ) ;
/* If an error occurred during request building, remove all HCI
* commands queued on the HCI request queue .
*/
if ( req - > err ) {
skb_queue_purge ( & req - > cmd_q ) ;
return req - > err ;
}
/* Do not allow empty requests */
if ( skb_queue_empty ( & req - > cmd_q ) )
return - ENODATA ;
skb = skb_peek_tail ( & req - > cmd_q ) ;
bt_cb ( skb ) - > hci . req_complete_skb = hci_cmd_sync_complete ;
bt_cb ( skb ) - > hci . req_flags | = HCI_REQ_SKB ;
spin_lock_irqsave ( & hdev - > cmd_q . lock , flags ) ;
skb_queue_splice_tail ( & req - > cmd_q , & hdev - > cmd_q ) ;
spin_unlock_irqrestore ( & hdev - > cmd_q . lock , flags ) ;
queue_work ( hdev - > workqueue , & hdev - > cmd_work ) ;
return 0 ;
}
/* This function requires the caller holds hdev->req_lock. */
struct sk_buff * __hci_cmd_sync_sk ( struct hci_dev * hdev , u16 opcode , u32 plen ,
const void * param , u8 event , u32 timeout ,
struct sock * sk )
{
struct hci_request req ;
struct sk_buff * skb ;
int err = 0 ;
bt_dev_dbg ( hdev , " " ) ;
hci_req_init ( & req , hdev ) ;
hci_cmd_sync_add ( & req , opcode , plen , param , event , sk ) ;
hdev - > req_status = HCI_REQ_PEND ;
err = hci_cmd_sync_run ( & req ) ;
if ( err < 0 )
return ERR_PTR ( err ) ;
err = wait_event_interruptible_timeout ( hdev - > req_wait_q ,
hdev - > req_status ! = HCI_REQ_PEND ,
timeout ) ;
if ( err = = - ERESTARTSYS )
return ERR_PTR ( - EINTR ) ;
switch ( hdev - > req_status ) {
case HCI_REQ_DONE :
err = - bt_to_errno ( hdev - > req_result ) ;
break ;
case HCI_REQ_CANCELED :
err = - hdev - > req_result ;
break ;
default :
err = - ETIMEDOUT ;
break ;
}
hdev - > req_status = 0 ;
hdev - > req_result = 0 ;
skb = hdev - > req_skb ;
hdev - > req_skb = NULL ;
bt_dev_dbg ( hdev , " end: err %d " , err ) ;
if ( err < 0 ) {
kfree_skb ( skb ) ;
return ERR_PTR ( err ) ;
}
return skb ;
}
EXPORT_SYMBOL ( __hci_cmd_sync_sk ) ;
/* This function requires the caller holds hdev->req_lock. */
struct sk_buff * __hci_cmd_sync ( struct hci_dev * hdev , u16 opcode , u32 plen ,
const void * param , u32 timeout )
{
return __hci_cmd_sync_sk ( hdev , opcode , plen , param , 0 , timeout , NULL ) ;
}
EXPORT_SYMBOL ( __hci_cmd_sync ) ;
/* Send HCI command and wait for command complete event */
struct sk_buff * hci_cmd_sync ( struct hci_dev * hdev , u16 opcode , u32 plen ,
const void * param , u32 timeout )
{
struct sk_buff * skb ;
if ( ! test_bit ( HCI_UP , & hdev - > flags ) )
return ERR_PTR ( - ENETDOWN ) ;
bt_dev_dbg ( hdev , " opcode 0x%4.4x plen %d " , opcode , plen ) ;
hci_req_sync_lock ( hdev ) ;
skb = __hci_cmd_sync ( hdev , opcode , plen , param , timeout ) ;
hci_req_sync_unlock ( hdev ) ;
return skb ;
}
EXPORT_SYMBOL ( hci_cmd_sync ) ;
/* This function requires the caller holds hdev->req_lock. */
struct sk_buff * __hci_cmd_sync_ev ( struct hci_dev * hdev , u16 opcode , u32 plen ,
const void * param , u8 event , u32 timeout )
{
return __hci_cmd_sync_sk ( hdev , opcode , plen , param , event , timeout ,
NULL ) ;
}
EXPORT_SYMBOL ( __hci_cmd_sync_ev ) ;
/* This function requires the caller holds hdev->req_lock. */
int __hci_cmd_sync_status_sk ( struct hci_dev * hdev , u16 opcode , u32 plen ,
const void * param , u8 event , u32 timeout ,
struct sock * sk )
{
struct sk_buff * skb ;
u8 status ;
skb = __hci_cmd_sync_sk ( hdev , opcode , plen , param , event , timeout , sk ) ;
Bluetooth: hci_sync: Convert MGMT_OP_START_DISCOVERY
This make use of hci_cmd_sync_queue for MGMT_OP_START_DISCOVERY,
MGMT_OP_START_SERVICE_DISCOVERY and MGMT_OP_STOP_DISCOVERY to use
hci_cmd_sync_queue so they no longer depend on hdev->discov_update work
to send any commands.
Tested with:
tools/mgmt-tester -s "Start Discovery"
Test Summary
------------
Start Discovery - Not powered 1 Passed
Start Discovery - Invalid parameters 1 Passed
Start Discovery - Not supported 1 Passed
Start Discovery - Success 1 Passed
Start Discovery - Success 2 Passed
Start Discovery - Power Off 1 Passed
Start Discovery BREDR LE - (Ext Scan Enable) Passed
Start Discovery LE - (Ext Scan Enable) Passed
Start Discovery LE - (Ext Scan Param) Passed
Start Discovery - (2m, Scan Param) Passed
Start Discovery - (coded, Scan Param) Passed
Start Discovery - (1m, 2m, coded, Scan Param) Passed
LL Privacy - Start Discovery 1 (Disable RL) Passed
LL Privacy - Start Discovery 2 (Disable RL) Passed
Total: 14, Passed: 14 (100.0%), Failed: 0, Not Run: 0
tools/mgmt-tester -s "Start Service"
Test Summary
------------
Start Service Discovery - Not powered 1 Passed
Start Service Discovery - Invalid parameters 1 Passed
Start Service Discovery - Not supported 1 Passed
Start Service Discovery - Success 1 Passed
Start Service Discovery - Success 2 Passed
Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0
tools/mgmt-tester -s "Stop Discovery"
Test Summary
------------
Stop Discovery - Success 1 Passed
Stop Discovery - BR/EDR (Inquiry) Success 1 Passed
Stop Discovery - Rejected 1 Passed
Stop Discovery - Invalid parameters 1 Passed
Stop Discovery - (Ext Scan Disable) Passed
Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-28 02:58:45 +03:00
if ( IS_ERR ( skb ) ) {
2021-10-28 02:58:38 +03:00
bt_dev_err ( hdev , " Opcode 0x%4x failed: %ld " , opcode ,
PTR_ERR ( skb ) ) ;
return PTR_ERR ( skb ) ;
}
Bluetooth: hci_sync: Convert MGMT_OP_START_DISCOVERY
This make use of hci_cmd_sync_queue for MGMT_OP_START_DISCOVERY,
MGMT_OP_START_SERVICE_DISCOVERY and MGMT_OP_STOP_DISCOVERY to use
hci_cmd_sync_queue so they no longer depend on hdev->discov_update work
to send any commands.
Tested with:
tools/mgmt-tester -s "Start Discovery"
Test Summary
------------
Start Discovery - Not powered 1 Passed
Start Discovery - Invalid parameters 1 Passed
Start Discovery - Not supported 1 Passed
Start Discovery - Success 1 Passed
Start Discovery - Success 2 Passed
Start Discovery - Power Off 1 Passed
Start Discovery BREDR LE - (Ext Scan Enable) Passed
Start Discovery LE - (Ext Scan Enable) Passed
Start Discovery LE - (Ext Scan Param) Passed
Start Discovery - (2m, Scan Param) Passed
Start Discovery - (coded, Scan Param) Passed
Start Discovery - (1m, 2m, coded, Scan Param) Passed
LL Privacy - Start Discovery 1 (Disable RL) Passed
LL Privacy - Start Discovery 2 (Disable RL) Passed
Total: 14, Passed: 14 (100.0%), Failed: 0, Not Run: 0
tools/mgmt-tester -s "Start Service"
Test Summary
------------
Start Service Discovery - Not powered 1 Passed
Start Service Discovery - Invalid parameters 1 Passed
Start Service Discovery - Not supported 1 Passed
Start Service Discovery - Success 1 Passed
Start Service Discovery - Success 2 Passed
Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0
tools/mgmt-tester -s "Stop Discovery"
Test Summary
------------
Stop Discovery - Success 1 Passed
Stop Discovery - BR/EDR (Inquiry) Success 1 Passed
Stop Discovery - Rejected 1 Passed
Stop Discovery - Invalid parameters 1 Passed
Stop Discovery - (Ext Scan Disable) Passed
Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-28 02:58:45 +03:00
/* If command return a status event skb will be set to NULL as there are
* no parameters , in case of failure IS_ERR ( skb ) would have be set to
* the actual error would be found with PTR_ERR ( skb ) .
*/
if ( ! skb )
return 0 ;
2021-10-28 02:58:38 +03:00
status = skb - > data [ 0 ] ;
kfree_skb ( skb ) ;
return status ;
}
EXPORT_SYMBOL ( __hci_cmd_sync_status_sk ) ;
int __hci_cmd_sync_status ( struct hci_dev * hdev , u16 opcode , u32 plen ,
const void * param , u32 timeout )
{
return __hci_cmd_sync_status_sk ( hdev , opcode , plen , param , 0 , timeout ,
NULL ) ;
}
EXPORT_SYMBOL ( __hci_cmd_sync_status ) ;
static void hci_cmd_sync_work ( struct work_struct * work )
{
struct hci_dev * hdev = container_of ( work , struct hci_dev , cmd_sync_work ) ;
struct hci_cmd_sync_work_entry * entry ;
hci_cmd_sync_work_func_t func ;
hci_cmd_sync_work_destroy_t destroy ;
void * data ;
bt_dev_dbg ( hdev , " " ) ;
mutex_lock ( & hdev - > cmd_sync_work_lock ) ;
entry = list_first_entry ( & hdev - > cmd_sync_work_list ,
struct hci_cmd_sync_work_entry , list ) ;
if ( entry ) {
list_del ( & entry - > list ) ;
func = entry - > func ;
data = entry - > data ;
destroy = entry - > destroy ;
kfree ( entry ) ;
} else {
func = NULL ;
data = NULL ;
destroy = NULL ;
}
mutex_unlock ( & hdev - > cmd_sync_work_lock ) ;
if ( func ) {
int err ;
hci_req_sync_lock ( hdev ) ;
err = func ( hdev , data ) ;
if ( destroy )
destroy ( hdev , data , err ) ;
hci_req_sync_unlock ( hdev ) ;
}
}
void hci_cmd_sync_init ( struct hci_dev * hdev )
{
INIT_WORK ( & hdev - > cmd_sync_work , hci_cmd_sync_work ) ;
INIT_LIST_HEAD ( & hdev - > cmd_sync_work_list ) ;
mutex_init ( & hdev - > cmd_sync_work_lock ) ;
}
void hci_cmd_sync_clear ( struct hci_dev * hdev )
{
struct hci_cmd_sync_work_entry * entry , * tmp ;
cancel_work_sync ( & hdev - > cmd_sync_work ) ;
list_for_each_entry_safe ( entry , tmp , & hdev - > cmd_sync_work_list , list ) {
if ( entry - > destroy )
entry - > destroy ( hdev , entry - > data , - ECANCELED ) ;
list_del ( & entry - > list ) ;
kfree ( entry ) ;
}
}
int hci_cmd_sync_queue ( struct hci_dev * hdev , hci_cmd_sync_work_func_t func ,
void * data , hci_cmd_sync_work_destroy_t destroy )
{
struct hci_cmd_sync_work_entry * entry ;
entry = kmalloc ( sizeof ( * entry ) , GFP_KERNEL ) ;
if ( ! entry )
return - ENOMEM ;
entry - > func = func ;
entry - > data = data ;
entry - > destroy = destroy ;
mutex_lock ( & hdev - > cmd_sync_work_lock ) ;
list_add_tail ( & entry - > list , & hdev - > cmd_sync_work_list ) ;
mutex_unlock ( & hdev - > cmd_sync_work_lock ) ;
queue_work ( hdev - > req_workqueue , & hdev - > cmd_sync_work ) ;
return 0 ;
}
EXPORT_SYMBOL ( hci_cmd_sync_queue ) ;
Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 1
This make use of hci_cmd_sync_queue for the following MGMT commands:
Set Device Class
Set Device ID
Add UUID
Remove UUID
tools/mgmt-tester -s "Set Device Class"
Test Summary
------------
Set Device Class - Success 1 Passed
Set Device Class - Success 2 Passed
Set Device Class - Invalid parameters 1 Passed
Total: 3, Passed: 3 (100.0%), Failed: 0, Not Run: 0
Overall execution time: 0.0599 seconds
tools/mgmt-tester -s "Set Device ID"
Test Summary
------------
Set Device ID - Success 1 Passed
Set Device ID - Success 2 Passed
Set Device ID - Disable Passed
Set Device ID - Power off and Power on Passed
Set Device ID - SSP off and Power on Passed
Set Device ID - Invalid Parameter Passed
Total: 6, Passed: 6 (100.0%), Failed: 0, Not Run: 0
Overall execution time: 0.107 seconds
tools/mgmt-tester -s "Add UUID"
Test Summary
------------
Add UUID - UUID-16 1 Passed
Add UUID - UUID-16 multiple 1 Passed
Add UUID - UUID-16 partial 1 Passed
Add UUID - UUID-32 1 Passed
Add UUID - UUID-32 multiple 1 Passed
Add UUID - UUID-32 partial 1 Passed
Add UUID - UUID-128 1 Passed
Add UUID - UUID-128 multiple 1 Passed
Add UUID - UUID-128 partial 1 Passed
Add UUID - UUID mix Passed
Total: 10, Passed: 10 (100.0%), Failed: 0, Not Run: 0
Overall execution time: 0.198 seconds
tools/mgmt-tester -s "Remove UUID"
Test Summary
------------
Remove UUID - Success 1 Passed
Remove UUID - All UUID - Success 2 Passed
Remove UUID - Power Off - Success 3 Passed
Remove UUID - Power Off and On - Success 4 Passed
Remove UUID - Not Exist - Invalid Params 1 Passed
Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0
Overall execution time: 0.0908 seconds
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-28 02:58:39 +03:00
int hci_update_eir_sync ( struct hci_dev * hdev )
{
struct hci_cp_write_eir cp ;
bt_dev_dbg ( hdev , " " ) ;
if ( ! hdev_is_powered ( hdev ) )
return 0 ;
if ( ! lmp_ext_inq_capable ( hdev ) )
return 0 ;
if ( ! hci_dev_test_flag ( hdev , HCI_SSP_ENABLED ) )
return 0 ;
if ( hci_dev_test_flag ( hdev , HCI_SERVICE_CACHE ) )
return 0 ;
memset ( & cp , 0 , sizeof ( cp ) ) ;
eir_create ( hdev , cp . data ) ;
if ( memcmp ( cp . data , hdev - > eir , sizeof ( cp . data ) ) = = 0 )
return 0 ;
memcpy ( hdev - > eir , cp . data , sizeof ( cp . data ) ) ;
return __hci_cmd_sync_status ( hdev , HCI_OP_WRITE_EIR , sizeof ( cp ) , & cp ,
HCI_CMD_TIMEOUT ) ;
}
static u8 get_service_classes ( struct hci_dev * hdev )
{
struct bt_uuid * uuid ;
u8 val = 0 ;
list_for_each_entry ( uuid , & hdev - > uuids , list )
val | = uuid - > svc_hint ;
return val ;
}
int hci_update_class_sync ( struct hci_dev * hdev )
{
u8 cod [ 3 ] ;
bt_dev_dbg ( hdev , " " ) ;
if ( ! hdev_is_powered ( hdev ) )
return 0 ;
if ( ! hci_dev_test_flag ( hdev , HCI_BREDR_ENABLED ) )
return 0 ;
if ( hci_dev_test_flag ( hdev , HCI_SERVICE_CACHE ) )
return 0 ;
cod [ 0 ] = hdev - > minor_class ;
cod [ 1 ] = hdev - > major_class ;
cod [ 2 ] = get_service_classes ( hdev ) ;
if ( hci_dev_test_flag ( hdev , HCI_LIMITED_DISCOVERABLE ) )
cod [ 1 ] | = 0x20 ;
if ( memcmp ( cod , hdev - > dev_class , 3 ) = = 0 )
return 0 ;
return __hci_cmd_sync_status ( hdev , HCI_OP_WRITE_CLASS_OF_DEV ,
sizeof ( cod ) , cod , HCI_CMD_TIMEOUT ) ;
}
Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 2
This make use of hci_cmd_sync_queue for the following MGMT commands:
Add Advertising
Remove Advertising
Add Extended Advertising Parameters
Add Extended Advertising Data
mgmt-tester -s "Add Advertising"
Test Summary
------------
Add Advertising - Failure: LE off Passed
Add Advertising - Invalid Params 1 (AD too long) Passed
Add Advertising - Invalid Params 2 (Malformed len) Passed
Add Advertising - Invalid Params 3 (Malformed len) Passed
Add Advertising - Invalid Params 4 (Malformed len) Passed
Add Advertising - Invalid Params 5 (AD too long) Passed
Add Advertising - Invalid Params 6 (ScRsp too long) Passed
Add Advertising - Invalid Params 7 (Malformed len) Passed
Add Advertising - Invalid Params 8 (Malformed len) Passed
Add Advertising - Invalid Params 9 (Malformed len) Passed
Add Advertising - Invalid Params 10 (ScRsp too long) Passed
Add Advertising - Rejected (Timeout, !Powered) Passed
Add Advertising - Success 1 (Powered, Add Adv Inst) Passed
Add Advertising - Success 2 (!Powered, Add Adv Inst) Passed
Add Advertising - Success 3 (!Powered, Adv Enable) Passed
Add Advertising - Success 4 (Set Adv on override) Passed
Add Advertising - Success 5 (Set Adv off override) Passed
Add Advertising - Success 6 (Scan Rsp Dta, Adv ok) Passed
Add Advertising - Success 7 (Scan Rsp Dta, Scan ok) Passed
Add Advertising - Success 8 (Connectable Flag) Passed
Add Advertising - Success 9 (General Discov Flag) Passed
Add Advertising - Success 10 (Limited Discov Flag) Passed
Add Advertising - Success 11 (Managed Flags) Passed
Add Advertising - Success 12 (TX Power Flag) Passed
Add Advertising - Success 13 (ADV_SCAN_IND) Passed
Add Advertising - Success 14 (ADV_NONCONN_IND) Passed
Add Advertising - Success 15 (ADV_IND) Passed
Add Advertising - Success 16 (Connectable -> on) Passed
Add Advertising - Success 17 (Connectable -> off) Passed
Add Advertising - Success 18 (Power -> off, Remove) Passed
Add Advertising - Success 19 (Power -> off, Keep) Passed
Add Advertising - Success 20 (Add Adv override) Passed
Add Advertising - Success 21 (Timeout expires) Passed
Add Advertising - Success 22 (LE -> off, Remove) Passed
Add Advertising - Success (Empty ScRsp) Passed
Add Advertising - Success (ScRsp only) Passed
Add Advertising - Invalid Params (ScRsp too long) Passed
Add Advertising - Success (ScRsp appear) Passed
Add Advertising - Invalid Params (ScRsp appear long) Passed
Add Advertising - Success (Appear is null) Passed
Add Advertising - Success (Name is null) Passed
Add Advertising - Success (Complete name) Passed
Add Advertising - Success (Shortened name) Passed
Add Advertising - Success (Short name) Passed
Add Advertising - Success (Name + data) Passed
Add Advertising - Invalid Params (Name + data) Passed
Add Advertising - Success (Name+data+appear) Passed
Total: 47, Passed: 47 (100.0%), Failed: 0, Not Run: 0
Overall execution time: 2.17 seconds
mgmt-tester -s "Remove Advertising"
Test Summary
------------
Remove Advertising - Invalid Params 1 Passed
Remove Advertising - Success 1 Passed
Remove Advertising - Success 2 Passed
Total: 3, Passed: 3 (100.0%), Failed: 0, Not Run: 0
Overall execution time: 0.0585 seconds
mgmt-tester -s "Ext Adv MGMT Params"
Test Summary:
------------
Ext Adv MGMT Params - Unpowered Passed
Ext Adv MGMT Params - Invalid parameters Passed
Ext Adv MGMT Params - Success Passed
Ext Adv MGMT Params - (5.0) Success Passed
Total: 4, Passed: 4 (100.0%), Failed: 0, Not Run: 0
Overall execution time: 0.0746 seconds
mgmt-tester -s "Ext Adv MGMT -"
Test Summary
------------
Ext Adv MGMT - Data set without Params Passed
Ext Adv MGMT - AD Data (5.0) Invalid parameters Passed
Ext Adv MGMT - AD Data (5.0) Success Passed
Ext Adv MGMT - AD Scan Response (5.0) Success Passed
Total: 4, Passed: 4 (100.0%), Failed: 0, Not Run: 0
Overall execution time: 0.0805 seconds
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-28 02:58:40 +03:00
static bool is_advertising_allowed ( struct hci_dev * hdev , bool connectable )
{
/* If there is no connection we are OK to advertise. */
if ( hci_conn_num ( hdev , LE_LINK ) = = 0 )
return true ;
/* Check le_states if there is any connection in peripheral role. */
if ( hdev - > conn_hash . le_num_peripheral > 0 ) {
/* Peripheral connection state and non connectable mode
* bit 20.
*/
if ( ! connectable & & ! ( hdev - > le_states [ 2 ] & 0x10 ) )
return false ;
/* Peripheral connection state and connectable mode bit 38
* and scannable bit 21.
*/
if ( connectable & & ( ! ( hdev - > le_states [ 4 ] & 0x40 ) | |
! ( hdev - > le_states [ 2 ] & 0x20 ) ) )
return false ;
}
/* Check le_states if there is any connection in central role. */
if ( hci_conn_num ( hdev , LE_LINK ) ! = hdev - > conn_hash . le_num_peripheral ) {
/* Central connection state and non connectable mode bit 18. */
if ( ! connectable & & ! ( hdev - > le_states [ 2 ] & 0x02 ) )
return false ;
/* Central connection state and connectable mode bit 35 and
* scannable 19.
*/
if ( connectable & & ( ! ( hdev - > le_states [ 4 ] & 0x08 ) | |
! ( hdev - > le_states [ 2 ] & 0x08 ) ) )
return false ;
}
return true ;
}
static bool adv_use_rpa ( struct hci_dev * hdev , uint32_t flags )
{
/* If privacy is not enabled don't use RPA */
if ( ! hci_dev_test_flag ( hdev , HCI_PRIVACY ) )
return false ;
/* If basic privacy mode is enabled use RPA */
if ( ! hci_dev_test_flag ( hdev , HCI_LIMITED_PRIVACY ) )
return true ;
/* If limited privacy mode is enabled don't use RPA if we're
* both discoverable and bondable .
*/
if ( ( flags & MGMT_ADV_FLAG_DISCOV ) & &
hci_dev_test_flag ( hdev , HCI_BONDABLE ) )
return false ;
/* We're neither bondable nor discoverable in the limited
* privacy mode , therefore use RPA .
*/
return true ;
}
static int hci_set_random_addr_sync ( struct hci_dev * hdev , bdaddr_t * rpa )
{
/* If we're advertising or initiating an LE connection we can't
* go ahead and change the random address at this time . This is
* because the eventual initiator address used for the
* subsequently created connection will be undefined ( some
* controllers use the new address and others the one we had
* when the operation started ) .
*
* In this kind of scenario skip the update and let the random
* address be updated at the next cycle .
*/
if ( hci_dev_test_flag ( hdev , HCI_LE_ADV ) | |
hci_lookup_le_connect ( hdev ) ) {
bt_dev_dbg ( hdev , " Deferring random address update " ) ;
hci_dev_set_flag ( hdev , HCI_RPA_EXPIRED ) ;
return 0 ;
}
return __hci_cmd_sync_status ( hdev , HCI_OP_LE_SET_RANDOM_ADDR ,
6 , rpa , HCI_CMD_TIMEOUT ) ;
}
int hci_update_random_address_sync ( struct hci_dev * hdev , bool require_privacy ,
bool rpa , u8 * own_addr_type )
{
int err ;
/* If privacy is enabled use a resolvable private address. If
* current RPA has expired or there is something else than
* the current RPA in use , then generate a new one .
*/
if ( rpa ) {
/* If Controller supports LL Privacy use own address type is
* 0x03
*/
2021-10-28 02:58:42 +03:00
if ( use_ll_privacy ( hdev ) )
Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 2
This make use of hci_cmd_sync_queue for the following MGMT commands:
Add Advertising
Remove Advertising
Add Extended Advertising Parameters
Add Extended Advertising Data
mgmt-tester -s "Add Advertising"
Test Summary
------------
Add Advertising - Failure: LE off Passed
Add Advertising - Invalid Params 1 (AD too long) Passed
Add Advertising - Invalid Params 2 (Malformed len) Passed
Add Advertising - Invalid Params 3 (Malformed len) Passed
Add Advertising - Invalid Params 4 (Malformed len) Passed
Add Advertising - Invalid Params 5 (AD too long) Passed
Add Advertising - Invalid Params 6 (ScRsp too long) Passed
Add Advertising - Invalid Params 7 (Malformed len) Passed
Add Advertising - Invalid Params 8 (Malformed len) Passed
Add Advertising - Invalid Params 9 (Malformed len) Passed
Add Advertising - Invalid Params 10 (ScRsp too long) Passed
Add Advertising - Rejected (Timeout, !Powered) Passed
Add Advertising - Success 1 (Powered, Add Adv Inst) Passed
Add Advertising - Success 2 (!Powered, Add Adv Inst) Passed
Add Advertising - Success 3 (!Powered, Adv Enable) Passed
Add Advertising - Success 4 (Set Adv on override) Passed
Add Advertising - Success 5 (Set Adv off override) Passed
Add Advertising - Success 6 (Scan Rsp Dta, Adv ok) Passed
Add Advertising - Success 7 (Scan Rsp Dta, Scan ok) Passed
Add Advertising - Success 8 (Connectable Flag) Passed
Add Advertising - Success 9 (General Discov Flag) Passed
Add Advertising - Success 10 (Limited Discov Flag) Passed
Add Advertising - Success 11 (Managed Flags) Passed
Add Advertising - Success 12 (TX Power Flag) Passed
Add Advertising - Success 13 (ADV_SCAN_IND) Passed
Add Advertising - Success 14 (ADV_NONCONN_IND) Passed
Add Advertising - Success 15 (ADV_IND) Passed
Add Advertising - Success 16 (Connectable -> on) Passed
Add Advertising - Success 17 (Connectable -> off) Passed
Add Advertising - Success 18 (Power -> off, Remove) Passed
Add Advertising - Success 19 (Power -> off, Keep) Passed
Add Advertising - Success 20 (Add Adv override) Passed
Add Advertising - Success 21 (Timeout expires) Passed
Add Advertising - Success 22 (LE -> off, Remove) Passed
Add Advertising - Success (Empty ScRsp) Passed
Add Advertising - Success (ScRsp only) Passed
Add Advertising - Invalid Params (ScRsp too long) Passed
Add Advertising - Success (ScRsp appear) Passed
Add Advertising - Invalid Params (ScRsp appear long) Passed
Add Advertising - Success (Appear is null) Passed
Add Advertising - Success (Name is null) Passed
Add Advertising - Success (Complete name) Passed
Add Advertising - Success (Shortened name) Passed
Add Advertising - Success (Short name) Passed
Add Advertising - Success (Name + data) Passed
Add Advertising - Invalid Params (Name + data) Passed
Add Advertising - Success (Name+data+appear) Passed
Total: 47, Passed: 47 (100.0%), Failed: 0, Not Run: 0
Overall execution time: 2.17 seconds
mgmt-tester -s "Remove Advertising"
Test Summary
------------
Remove Advertising - Invalid Params 1 Passed
Remove Advertising - Success 1 Passed
Remove Advertising - Success 2 Passed
Total: 3, Passed: 3 (100.0%), Failed: 0, Not Run: 0
Overall execution time: 0.0585 seconds
mgmt-tester -s "Ext Adv MGMT Params"
Test Summary:
------------
Ext Adv MGMT Params - Unpowered Passed
Ext Adv MGMT Params - Invalid parameters Passed
Ext Adv MGMT Params - Success Passed
Ext Adv MGMT Params - (5.0) Success Passed
Total: 4, Passed: 4 (100.0%), Failed: 0, Not Run: 0
Overall execution time: 0.0746 seconds
mgmt-tester -s "Ext Adv MGMT -"
Test Summary
------------
Ext Adv MGMT - Data set without Params Passed
Ext Adv MGMT - AD Data (5.0) Invalid parameters Passed
Ext Adv MGMT - AD Data (5.0) Success Passed
Ext Adv MGMT - AD Scan Response (5.0) Success Passed
Total: 4, Passed: 4 (100.0%), Failed: 0, Not Run: 0
Overall execution time: 0.0805 seconds
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-28 02:58:40 +03:00
* own_addr_type = ADDR_LE_DEV_RANDOM_RESOLVED ;
else
* own_addr_type = ADDR_LE_DEV_RANDOM ;
/* Check if RPA is valid */
if ( rpa_valid ( hdev ) )
return 0 ;
err = smp_generate_rpa ( hdev , hdev - > irk , & hdev - > rpa ) ;
if ( err < 0 ) {
bt_dev_err ( hdev , " failed to generate new RPA " ) ;
return err ;
}
err = hci_set_random_addr_sync ( hdev , & hdev - > rpa ) ;
if ( err )
return err ;
return 0 ;
}
/* In case of required privacy without resolvable private address,
* use an non - resolvable private address . This is useful for active
* scanning and non - connectable advertising .
*/
if ( require_privacy ) {
bdaddr_t nrpa ;
while ( true ) {
/* The non-resolvable private address is generated
* from random six bytes with the two most significant
* bits cleared .
*/
get_random_bytes ( & nrpa , 6 ) ;
nrpa . b [ 5 ] & = 0x3f ;
/* The non-resolvable private address shall not be
* equal to the public address .
*/
if ( bacmp ( & hdev - > bdaddr , & nrpa ) )
break ;
}
* own_addr_type = ADDR_LE_DEV_RANDOM ;
return hci_set_random_addr_sync ( hdev , & nrpa ) ;
}
/* If forcing static address is in use or there is no public
* address use the static address as random address ( but skip
* the HCI command if the current random address is already the
* static one .
*
* In case BR / EDR has been disabled on a dual - mode controller
* and a static address has been configured , then use that
* address instead of the public BR / EDR address .
*/
if ( hci_dev_test_flag ( hdev , HCI_FORCE_STATIC_ADDR ) | |
! bacmp ( & hdev - > bdaddr , BDADDR_ANY ) | |
( ! hci_dev_test_flag ( hdev , HCI_BREDR_ENABLED ) & &
bacmp ( & hdev - > static_addr , BDADDR_ANY ) ) ) {
* own_addr_type = ADDR_LE_DEV_RANDOM ;
if ( bacmp ( & hdev - > static_addr , & hdev - > random_addr ) )
return hci_set_random_addr_sync ( hdev ,
& hdev - > static_addr ) ;
return 0 ;
}
/* Neither privacy nor static address is being used so use a
* public address .
*/
* own_addr_type = ADDR_LE_DEV_PUBLIC ;
return 0 ;
}
static int hci_disable_ext_adv_instance_sync ( struct hci_dev * hdev , u8 instance )
{
struct hci_cp_le_set_ext_adv_enable * cp ;
struct hci_cp_ext_adv_set * set ;
u8 data [ sizeof ( * cp ) + sizeof ( * set ) * 1 ] ;
u8 size ;
/* If request specifies an instance that doesn't exist, fail */
if ( instance > 0 ) {
struct adv_info * adv ;
adv = hci_find_adv_instance ( hdev , instance ) ;
if ( ! adv )
return - EINVAL ;
/* If not enabled there is nothing to do */
if ( ! adv - > enabled )
return 0 ;
}
memset ( data , 0 , sizeof ( data ) ) ;
cp = ( void * ) data ;
set = ( void * ) cp - > data ;
/* Instance 0x00 indicates all advertising instances will be disabled */
cp - > num_of_sets = ! ! instance ;
cp - > enable = 0x00 ;
set - > handle = instance ;
size = sizeof ( * cp ) + sizeof ( * set ) * cp - > num_of_sets ;
return __hci_cmd_sync_status ( hdev , HCI_OP_LE_SET_EXT_ADV_ENABLE ,
size , data , HCI_CMD_TIMEOUT ) ;
}
static int hci_set_adv_set_random_addr_sync ( struct hci_dev * hdev , u8 instance ,
bdaddr_t * random_addr )
{
struct hci_cp_le_set_adv_set_rand_addr cp ;
int err ;
if ( ! instance ) {
/* Instance 0x00 doesn't have an adv_info, instead it uses
* hdev - > random_addr to track its address so whenever it needs
* to be updated this also set the random address since
* hdev - > random_addr is shared with scan state machine .
*/
err = hci_set_random_addr_sync ( hdev , random_addr ) ;
if ( err )
return err ;
}
memset ( & cp , 0 , sizeof ( cp ) ) ;
cp . handle = instance ;
bacpy ( & cp . bdaddr , random_addr ) ;
return __hci_cmd_sync_status ( hdev , HCI_OP_LE_SET_ADV_SET_RAND_ADDR ,
sizeof ( cp ) , & cp , HCI_CMD_TIMEOUT ) ;
}
int hci_setup_ext_adv_instance_sync ( struct hci_dev * hdev , u8 instance )
{
struct hci_cp_le_set_ext_adv_params cp ;
bool connectable ;
u32 flags ;
bdaddr_t random_addr ;
u8 own_addr_type ;
int err ;
struct adv_info * adv ;
bool secondary_adv ;
if ( instance > 0 ) {
adv = hci_find_adv_instance ( hdev , instance ) ;
if ( ! adv )
return - EINVAL ;
} else {
adv = NULL ;
}
/* Updating parameters of an active instance will return a
* Command Disallowed error , so we must first disable the
* instance if it is active .
*/
if ( adv & & ! adv - > pending ) {
err = hci_disable_ext_adv_instance_sync ( hdev , instance ) ;
if ( err )
return err ;
}
flags = hci_adv_instance_flags ( hdev , instance ) ;
/* If the "connectable" instance flag was not set, then choose between
* ADV_IND and ADV_NONCONN_IND based on the global connectable setting .
*/
connectable = ( flags & MGMT_ADV_FLAG_CONNECTABLE ) | |
mgmt_get_connectable ( hdev ) ;
if ( ! is_advertising_allowed ( hdev , connectable ) )
return - EPERM ;
/* Set require_privacy to true only when non-connectable
* advertising is used . In that case it is fine to use a
* non - resolvable private address .
*/
err = hci_get_random_address ( hdev , ! connectable ,
adv_use_rpa ( hdev , flags ) , adv ,
& own_addr_type , & random_addr ) ;
if ( err < 0 )
return err ;
memset ( & cp , 0 , sizeof ( cp ) ) ;
if ( adv ) {
hci_cpu_to_le24 ( adv - > min_interval , cp . min_interval ) ;
hci_cpu_to_le24 ( adv - > max_interval , cp . max_interval ) ;
cp . tx_power = adv - > tx_power ;
} else {
hci_cpu_to_le24 ( hdev - > le_adv_min_interval , cp . min_interval ) ;
hci_cpu_to_le24 ( hdev - > le_adv_max_interval , cp . max_interval ) ;
cp . tx_power = HCI_ADV_TX_POWER_NO_PREFERENCE ;
}
secondary_adv = ( flags & MGMT_ADV_FLAG_SEC_MASK ) ;
if ( connectable ) {
if ( secondary_adv )
cp . evt_properties = cpu_to_le16 ( LE_EXT_ADV_CONN_IND ) ;
else
cp . evt_properties = cpu_to_le16 ( LE_LEGACY_ADV_IND ) ;
} else if ( hci_adv_instance_is_scannable ( hdev , instance ) | |
( flags & MGMT_ADV_PARAM_SCAN_RSP ) ) {
if ( secondary_adv )
cp . evt_properties = cpu_to_le16 ( LE_EXT_ADV_SCAN_IND ) ;
else
cp . evt_properties = cpu_to_le16 ( LE_LEGACY_ADV_SCAN_IND ) ;
} else {
if ( secondary_adv )
cp . evt_properties = cpu_to_le16 ( LE_EXT_ADV_NON_CONN_IND ) ;
else
cp . evt_properties = cpu_to_le16 ( LE_LEGACY_NONCONN_IND ) ;
}
2021-10-28 02:58:44 +03:00
/* If Own_Address_Type equals 0x02 or 0x03, the Peer_Address parameter
* contains the peer ’ s Identity Address and the Peer_Address_Type
* parameter contains the peer ’ s Identity Type ( i . e . , 0x00 or 0x01 ) .
* These parameters are used to locate the corresponding local IRK in
* the resolving list ; this IRK is used to generate their own address
* used in the advertisement .
*/
if ( own_addr_type = = ADDR_LE_DEV_RANDOM_RESOLVED )
hci_copy_identity_address ( hdev , & cp . peer_addr ,
& cp . peer_addr_type ) ;
Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 2
This make use of hci_cmd_sync_queue for the following MGMT commands:
Add Advertising
Remove Advertising
Add Extended Advertising Parameters
Add Extended Advertising Data
mgmt-tester -s "Add Advertising"
Test Summary
------------
Add Advertising - Failure: LE off Passed
Add Advertising - Invalid Params 1 (AD too long) Passed
Add Advertising - Invalid Params 2 (Malformed len) Passed
Add Advertising - Invalid Params 3 (Malformed len) Passed
Add Advertising - Invalid Params 4 (Malformed len) Passed
Add Advertising - Invalid Params 5 (AD too long) Passed
Add Advertising - Invalid Params 6 (ScRsp too long) Passed
Add Advertising - Invalid Params 7 (Malformed len) Passed
Add Advertising - Invalid Params 8 (Malformed len) Passed
Add Advertising - Invalid Params 9 (Malformed len) Passed
Add Advertising - Invalid Params 10 (ScRsp too long) Passed
Add Advertising - Rejected (Timeout, !Powered) Passed
Add Advertising - Success 1 (Powered, Add Adv Inst) Passed
Add Advertising - Success 2 (!Powered, Add Adv Inst) Passed
Add Advertising - Success 3 (!Powered, Adv Enable) Passed
Add Advertising - Success 4 (Set Adv on override) Passed
Add Advertising - Success 5 (Set Adv off override) Passed
Add Advertising - Success 6 (Scan Rsp Dta, Adv ok) Passed
Add Advertising - Success 7 (Scan Rsp Dta, Scan ok) Passed
Add Advertising - Success 8 (Connectable Flag) Passed
Add Advertising - Success 9 (General Discov Flag) Passed
Add Advertising - Success 10 (Limited Discov Flag) Passed
Add Advertising - Success 11 (Managed Flags) Passed
Add Advertising - Success 12 (TX Power Flag) Passed
Add Advertising - Success 13 (ADV_SCAN_IND) Passed
Add Advertising - Success 14 (ADV_NONCONN_IND) Passed
Add Advertising - Success 15 (ADV_IND) Passed
Add Advertising - Success 16 (Connectable -> on) Passed
Add Advertising - Success 17 (Connectable -> off) Passed
Add Advertising - Success 18 (Power -> off, Remove) Passed
Add Advertising - Success 19 (Power -> off, Keep) Passed
Add Advertising - Success 20 (Add Adv override) Passed
Add Advertising - Success 21 (Timeout expires) Passed
Add Advertising - Success 22 (LE -> off, Remove) Passed
Add Advertising - Success (Empty ScRsp) Passed
Add Advertising - Success (ScRsp only) Passed
Add Advertising - Invalid Params (ScRsp too long) Passed
Add Advertising - Success (ScRsp appear) Passed
Add Advertising - Invalid Params (ScRsp appear long) Passed
Add Advertising - Success (Appear is null) Passed
Add Advertising - Success (Name is null) Passed
Add Advertising - Success (Complete name) Passed
Add Advertising - Success (Shortened name) Passed
Add Advertising - Success (Short name) Passed
Add Advertising - Success (Name + data) Passed
Add Advertising - Invalid Params (Name + data) Passed
Add Advertising - Success (Name+data+appear) Passed
Total: 47, Passed: 47 (100.0%), Failed: 0, Not Run: 0
Overall execution time: 2.17 seconds
mgmt-tester -s "Remove Advertising"
Test Summary
------------
Remove Advertising - Invalid Params 1 Passed
Remove Advertising - Success 1 Passed
Remove Advertising - Success 2 Passed
Total: 3, Passed: 3 (100.0%), Failed: 0, Not Run: 0
Overall execution time: 0.0585 seconds
mgmt-tester -s "Ext Adv MGMT Params"
Test Summary:
------------
Ext Adv MGMT Params - Unpowered Passed
Ext Adv MGMT Params - Invalid parameters Passed
Ext Adv MGMT Params - Success Passed
Ext Adv MGMT Params - (5.0) Success Passed
Total: 4, Passed: 4 (100.0%), Failed: 0, Not Run: 0
Overall execution time: 0.0746 seconds
mgmt-tester -s "Ext Adv MGMT -"
Test Summary
------------
Ext Adv MGMT - Data set without Params Passed
Ext Adv MGMT - AD Data (5.0) Invalid parameters Passed
Ext Adv MGMT - AD Data (5.0) Success Passed
Ext Adv MGMT - AD Scan Response (5.0) Success Passed
Total: 4, Passed: 4 (100.0%), Failed: 0, Not Run: 0
Overall execution time: 0.0805 seconds
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-28 02:58:40 +03:00
cp . own_addr_type = own_addr_type ;
cp . channel_map = hdev - > le_adv_channel_map ;
cp . handle = instance ;
if ( flags & MGMT_ADV_FLAG_SEC_2M ) {
cp . primary_phy = HCI_ADV_PHY_1M ;
cp . secondary_phy = HCI_ADV_PHY_2M ;
} else if ( flags & MGMT_ADV_FLAG_SEC_CODED ) {
cp . primary_phy = HCI_ADV_PHY_CODED ;
cp . secondary_phy = HCI_ADV_PHY_CODED ;
} else {
/* In all other cases use 1M */
cp . primary_phy = HCI_ADV_PHY_1M ;
cp . secondary_phy = HCI_ADV_PHY_1M ;
}
err = __hci_cmd_sync_status ( hdev , HCI_OP_LE_SET_EXT_ADV_PARAMS ,
sizeof ( cp ) , & cp , HCI_CMD_TIMEOUT ) ;
if ( err )
return err ;
if ( ( own_addr_type = = ADDR_LE_DEV_RANDOM | |
own_addr_type = = ADDR_LE_DEV_RANDOM_RESOLVED ) & &
bacmp ( & random_addr , BDADDR_ANY ) ) {
/* Check if random address need to be updated */
if ( adv ) {
if ( ! bacmp ( & random_addr , & adv - > random_addr ) )
return 0 ;
} else {
if ( ! bacmp ( & random_addr , & hdev - > random_addr ) )
return 0 ;
}
return hci_set_adv_set_random_addr_sync ( hdev , instance ,
& random_addr ) ;
}
return 0 ;
}
static int hci_set_ext_scan_rsp_data_sync ( struct hci_dev * hdev , u8 instance )
{
struct {
struct hci_cp_le_set_ext_scan_rsp_data cp ;
u8 data [ HCI_MAX_EXT_AD_LENGTH ] ;
} pdu ;
u8 len ;
memset ( & pdu , 0 , sizeof ( pdu ) ) ;
len = eir_create_scan_rsp ( hdev , instance , pdu . data ) ;
if ( hdev - > scan_rsp_data_len = = len & &
! memcmp ( pdu . data , hdev - > scan_rsp_data , len ) )
return 0 ;
memcpy ( hdev - > scan_rsp_data , pdu . data , len ) ;
hdev - > scan_rsp_data_len = len ;
pdu . cp . handle = instance ;
pdu . cp . length = len ;
pdu . cp . operation = LE_SET_ADV_DATA_OP_COMPLETE ;
pdu . cp . frag_pref = LE_SET_ADV_DATA_NO_FRAG ;
return __hci_cmd_sync_status ( hdev , HCI_OP_LE_SET_EXT_SCAN_RSP_DATA ,
sizeof ( pdu . cp ) + len , & pdu . cp ,
HCI_CMD_TIMEOUT ) ;
}
static int __hci_set_scan_rsp_data_sync ( struct hci_dev * hdev , u8 instance )
{
struct hci_cp_le_set_scan_rsp_data cp ;
u8 len ;
memset ( & cp , 0 , sizeof ( cp ) ) ;
len = eir_create_scan_rsp ( hdev , instance , cp . data ) ;
if ( hdev - > scan_rsp_data_len = = len & &
! memcmp ( cp . data , hdev - > scan_rsp_data , len ) )
return 0 ;
memcpy ( hdev - > scan_rsp_data , cp . data , sizeof ( cp . data ) ) ;
hdev - > scan_rsp_data_len = len ;
cp . length = len ;
return __hci_cmd_sync_status ( hdev , HCI_OP_LE_SET_SCAN_RSP_DATA ,
sizeof ( cp ) , & cp , HCI_CMD_TIMEOUT ) ;
}
int hci_update_scan_rsp_data_sync ( struct hci_dev * hdev , u8 instance )
{
if ( ! hci_dev_test_flag ( hdev , HCI_LE_ENABLED ) )
return 0 ;
if ( ext_adv_capable ( hdev ) )
return hci_set_ext_scan_rsp_data_sync ( hdev , instance ) ;
return __hci_set_scan_rsp_data_sync ( hdev , instance ) ;
}
int hci_enable_ext_advertising_sync ( struct hci_dev * hdev , u8 instance )
{
struct hci_cp_le_set_ext_adv_enable * cp ;
struct hci_cp_ext_adv_set * set ;
u8 data [ sizeof ( * cp ) + sizeof ( * set ) * 1 ] ;
struct adv_info * adv ;
if ( instance > 0 ) {
adv = hci_find_adv_instance ( hdev , instance ) ;
if ( ! adv )
return - EINVAL ;
/* If already enabled there is nothing to do */
if ( adv - > enabled )
return 0 ;
} else {
adv = NULL ;
}
cp = ( void * ) data ;
set = ( void * ) cp - > data ;
memset ( cp , 0 , sizeof ( * cp ) ) ;
cp - > enable = 0x01 ;
cp - > num_of_sets = 0x01 ;
memset ( set , 0 , sizeof ( * set ) ) ;
set - > handle = instance ;
/* Set duration per instance since controller is responsible for
* scheduling it .
*/
if ( adv & & adv - > duration ) {
u16 duration = adv - > timeout * MSEC_PER_SEC ;
/* Time = N * 10 ms */
set - > duration = cpu_to_le16 ( duration / 10 ) ;
}
return __hci_cmd_sync_status ( hdev , HCI_OP_LE_SET_EXT_ADV_ENABLE ,
sizeof ( * cp ) +
sizeof ( * set ) * cp - > num_of_sets ,
data , HCI_CMD_TIMEOUT ) ;
}
int hci_start_ext_adv_sync ( struct hci_dev * hdev , u8 instance )
{
int err ;
err = hci_setup_ext_adv_instance_sync ( hdev , instance ) ;
if ( err )
return err ;
err = hci_set_ext_scan_rsp_data_sync ( hdev , instance ) ;
if ( err )
return err ;
return hci_enable_ext_advertising_sync ( hdev , instance ) ;
}
static int hci_start_adv_sync ( struct hci_dev * hdev , u8 instance )
{
int err ;
if ( ext_adv_capable ( hdev ) )
return hci_start_ext_adv_sync ( hdev , instance ) ;
err = hci_update_adv_data_sync ( hdev , instance ) ;
if ( err )
return err ;
err = hci_update_scan_rsp_data_sync ( hdev , instance ) ;
if ( err )
return err ;
return hci_enable_advertising_sync ( hdev ) ;
}
int hci_enable_advertising_sync ( struct hci_dev * hdev )
{
struct adv_info * adv_instance ;
struct hci_cp_le_set_adv_param cp ;
u8 own_addr_type , enable = 0x01 ;
bool connectable ;
u16 adv_min_interval , adv_max_interval ;
u32 flags ;
u8 status ;
2021-10-28 02:58:42 +03:00
if ( ext_adv_capable ( hdev ) )
return hci_enable_ext_advertising_sync ( hdev ,
hdev - > cur_adv_instance ) ;
Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 2
This make use of hci_cmd_sync_queue for the following MGMT commands:
Add Advertising
Remove Advertising
Add Extended Advertising Parameters
Add Extended Advertising Data
mgmt-tester -s "Add Advertising"
Test Summary
------------
Add Advertising - Failure: LE off Passed
Add Advertising - Invalid Params 1 (AD too long) Passed
Add Advertising - Invalid Params 2 (Malformed len) Passed
Add Advertising - Invalid Params 3 (Malformed len) Passed
Add Advertising - Invalid Params 4 (Malformed len) Passed
Add Advertising - Invalid Params 5 (AD too long) Passed
Add Advertising - Invalid Params 6 (ScRsp too long) Passed
Add Advertising - Invalid Params 7 (Malformed len) Passed
Add Advertising - Invalid Params 8 (Malformed len) Passed
Add Advertising - Invalid Params 9 (Malformed len) Passed
Add Advertising - Invalid Params 10 (ScRsp too long) Passed
Add Advertising - Rejected (Timeout, !Powered) Passed
Add Advertising - Success 1 (Powered, Add Adv Inst) Passed
Add Advertising - Success 2 (!Powered, Add Adv Inst) Passed
Add Advertising - Success 3 (!Powered, Adv Enable) Passed
Add Advertising - Success 4 (Set Adv on override) Passed
Add Advertising - Success 5 (Set Adv off override) Passed
Add Advertising - Success 6 (Scan Rsp Dta, Adv ok) Passed
Add Advertising - Success 7 (Scan Rsp Dta, Scan ok) Passed
Add Advertising - Success 8 (Connectable Flag) Passed
Add Advertising - Success 9 (General Discov Flag) Passed
Add Advertising - Success 10 (Limited Discov Flag) Passed
Add Advertising - Success 11 (Managed Flags) Passed
Add Advertising - Success 12 (TX Power Flag) Passed
Add Advertising - Success 13 (ADV_SCAN_IND) Passed
Add Advertising - Success 14 (ADV_NONCONN_IND) Passed
Add Advertising - Success 15 (ADV_IND) Passed
Add Advertising - Success 16 (Connectable -> on) Passed
Add Advertising - Success 17 (Connectable -> off) Passed
Add Advertising - Success 18 (Power -> off, Remove) Passed
Add Advertising - Success 19 (Power -> off, Keep) Passed
Add Advertising - Success 20 (Add Adv override) Passed
Add Advertising - Success 21 (Timeout expires) Passed
Add Advertising - Success 22 (LE -> off, Remove) Passed
Add Advertising - Success (Empty ScRsp) Passed
Add Advertising - Success (ScRsp only) Passed
Add Advertising - Invalid Params (ScRsp too long) Passed
Add Advertising - Success (ScRsp appear) Passed
Add Advertising - Invalid Params (ScRsp appear long) Passed
Add Advertising - Success (Appear is null) Passed
Add Advertising - Success (Name is null) Passed
Add Advertising - Success (Complete name) Passed
Add Advertising - Success (Shortened name) Passed
Add Advertising - Success (Short name) Passed
Add Advertising - Success (Name + data) Passed
Add Advertising - Invalid Params (Name + data) Passed
Add Advertising - Success (Name+data+appear) Passed
Total: 47, Passed: 47 (100.0%), Failed: 0, Not Run: 0
Overall execution time: 2.17 seconds
mgmt-tester -s "Remove Advertising"
Test Summary
------------
Remove Advertising - Invalid Params 1 Passed
Remove Advertising - Success 1 Passed
Remove Advertising - Success 2 Passed
Total: 3, Passed: 3 (100.0%), Failed: 0, Not Run: 0
Overall execution time: 0.0585 seconds
mgmt-tester -s "Ext Adv MGMT Params"
Test Summary:
------------
Ext Adv MGMT Params - Unpowered Passed
Ext Adv MGMT Params - Invalid parameters Passed
Ext Adv MGMT Params - Success Passed
Ext Adv MGMT Params - (5.0) Success Passed
Total: 4, Passed: 4 (100.0%), Failed: 0, Not Run: 0
Overall execution time: 0.0746 seconds
mgmt-tester -s "Ext Adv MGMT -"
Test Summary
------------
Ext Adv MGMT - Data set without Params Passed
Ext Adv MGMT - AD Data (5.0) Invalid parameters Passed
Ext Adv MGMT - AD Data (5.0) Success Passed
Ext Adv MGMT - AD Scan Response (5.0) Success Passed
Total: 4, Passed: 4 (100.0%), Failed: 0, Not Run: 0
Overall execution time: 0.0805 seconds
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-28 02:58:40 +03:00
flags = hci_adv_instance_flags ( hdev , hdev - > cur_adv_instance ) ;
adv_instance = hci_find_adv_instance ( hdev , hdev - > cur_adv_instance ) ;
/* If the "connectable" instance flag was not set, then choose between
* ADV_IND and ADV_NONCONN_IND based on the global connectable setting .
*/
connectable = ( flags & MGMT_ADV_FLAG_CONNECTABLE ) | |
mgmt_get_connectable ( hdev ) ;
if ( ! is_advertising_allowed ( hdev , connectable ) )
return - EINVAL ;
2021-10-28 02:58:42 +03:00
status = hci_disable_advertising_sync ( hdev ) ;
if ( status )
return status ;
Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 2
This make use of hci_cmd_sync_queue for the following MGMT commands:
Add Advertising
Remove Advertising
Add Extended Advertising Parameters
Add Extended Advertising Data
mgmt-tester -s "Add Advertising"
Test Summary
------------
Add Advertising - Failure: LE off Passed
Add Advertising - Invalid Params 1 (AD too long) Passed
Add Advertising - Invalid Params 2 (Malformed len) Passed
Add Advertising - Invalid Params 3 (Malformed len) Passed
Add Advertising - Invalid Params 4 (Malformed len) Passed
Add Advertising - Invalid Params 5 (AD too long) Passed
Add Advertising - Invalid Params 6 (ScRsp too long) Passed
Add Advertising - Invalid Params 7 (Malformed len) Passed
Add Advertising - Invalid Params 8 (Malformed len) Passed
Add Advertising - Invalid Params 9 (Malformed len) Passed
Add Advertising - Invalid Params 10 (ScRsp too long) Passed
Add Advertising - Rejected (Timeout, !Powered) Passed
Add Advertising - Success 1 (Powered, Add Adv Inst) Passed
Add Advertising - Success 2 (!Powered, Add Adv Inst) Passed
Add Advertising - Success 3 (!Powered, Adv Enable) Passed
Add Advertising - Success 4 (Set Adv on override) Passed
Add Advertising - Success 5 (Set Adv off override) Passed
Add Advertising - Success 6 (Scan Rsp Dta, Adv ok) Passed
Add Advertising - Success 7 (Scan Rsp Dta, Scan ok) Passed
Add Advertising - Success 8 (Connectable Flag) Passed
Add Advertising - Success 9 (General Discov Flag) Passed
Add Advertising - Success 10 (Limited Discov Flag) Passed
Add Advertising - Success 11 (Managed Flags) Passed
Add Advertising - Success 12 (TX Power Flag) Passed
Add Advertising - Success 13 (ADV_SCAN_IND) Passed
Add Advertising - Success 14 (ADV_NONCONN_IND) Passed
Add Advertising - Success 15 (ADV_IND) Passed
Add Advertising - Success 16 (Connectable -> on) Passed
Add Advertising - Success 17 (Connectable -> off) Passed
Add Advertising - Success 18 (Power -> off, Remove) Passed
Add Advertising - Success 19 (Power -> off, Keep) Passed
Add Advertising - Success 20 (Add Adv override) Passed
Add Advertising - Success 21 (Timeout expires) Passed
Add Advertising - Success 22 (LE -> off, Remove) Passed
Add Advertising - Success (Empty ScRsp) Passed
Add Advertising - Success (ScRsp only) Passed
Add Advertising - Invalid Params (ScRsp too long) Passed
Add Advertising - Success (ScRsp appear) Passed
Add Advertising - Invalid Params (ScRsp appear long) Passed
Add Advertising - Success (Appear is null) Passed
Add Advertising - Success (Name is null) Passed
Add Advertising - Success (Complete name) Passed
Add Advertising - Success (Shortened name) Passed
Add Advertising - Success (Short name) Passed
Add Advertising - Success (Name + data) Passed
Add Advertising - Invalid Params (Name + data) Passed
Add Advertising - Success (Name+data+appear) Passed
Total: 47, Passed: 47 (100.0%), Failed: 0, Not Run: 0
Overall execution time: 2.17 seconds
mgmt-tester -s "Remove Advertising"
Test Summary
------------
Remove Advertising - Invalid Params 1 Passed
Remove Advertising - Success 1 Passed
Remove Advertising - Success 2 Passed
Total: 3, Passed: 3 (100.0%), Failed: 0, Not Run: 0
Overall execution time: 0.0585 seconds
mgmt-tester -s "Ext Adv MGMT Params"
Test Summary:
------------
Ext Adv MGMT Params - Unpowered Passed
Ext Adv MGMT Params - Invalid parameters Passed
Ext Adv MGMT Params - Success Passed
Ext Adv MGMT Params - (5.0) Success Passed
Total: 4, Passed: 4 (100.0%), Failed: 0, Not Run: 0
Overall execution time: 0.0746 seconds
mgmt-tester -s "Ext Adv MGMT -"
Test Summary
------------
Ext Adv MGMT - Data set without Params Passed
Ext Adv MGMT - AD Data (5.0) Invalid parameters Passed
Ext Adv MGMT - AD Data (5.0) Success Passed
Ext Adv MGMT - AD Scan Response (5.0) Success Passed
Total: 4, Passed: 4 (100.0%), Failed: 0, Not Run: 0
Overall execution time: 0.0805 seconds
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-28 02:58:40 +03:00
/* Clear the HCI_LE_ADV bit temporarily so that the
* hci_update_random_address knows that it ' s safe to go ahead
* and write a new random address . The flag will be set back on
* as soon as the SET_ADV_ENABLE HCI command completes .
*/
hci_dev_clear_flag ( hdev , HCI_LE_ADV ) ;
/* Set require_privacy to true only when non-connectable
* advertising is used . In that case it is fine to use a
* non - resolvable private address .
*/
status = hci_update_random_address_sync ( hdev , ! connectable ,
adv_use_rpa ( hdev , flags ) ,
& own_addr_type ) ;
if ( status )
return status ;
memset ( & cp , 0 , sizeof ( cp ) ) ;
if ( adv_instance ) {
adv_min_interval = adv_instance - > min_interval ;
adv_max_interval = adv_instance - > max_interval ;
} else {
adv_min_interval = hdev - > le_adv_min_interval ;
adv_max_interval = hdev - > le_adv_max_interval ;
}
if ( connectable ) {
cp . type = LE_ADV_IND ;
} else {
if ( hci_adv_instance_is_scannable ( hdev , hdev - > cur_adv_instance ) )
cp . type = LE_ADV_SCAN_IND ;
else
cp . type = LE_ADV_NONCONN_IND ;
if ( ! hci_dev_test_flag ( hdev , HCI_DISCOVERABLE ) | |
hci_dev_test_flag ( hdev , HCI_LIMITED_DISCOVERABLE ) ) {
adv_min_interval = DISCOV_LE_FAST_ADV_INT_MIN ;
adv_max_interval = DISCOV_LE_FAST_ADV_INT_MAX ;
}
}
cp . min_interval = cpu_to_le16 ( adv_min_interval ) ;
cp . max_interval = cpu_to_le16 ( adv_max_interval ) ;
cp . own_address_type = own_addr_type ;
cp . channel_map = hdev - > le_adv_channel_map ;
status = __hci_cmd_sync_status ( hdev , HCI_OP_LE_SET_ADV_PARAM ,
sizeof ( cp ) , & cp , HCI_CMD_TIMEOUT ) ;
if ( status )
return status ;
return __hci_cmd_sync_status ( hdev , HCI_OP_LE_SET_ADV_ENABLE ,
sizeof ( enable ) , & enable , HCI_CMD_TIMEOUT ) ;
}
Bluetooth: hci_sync: Convert MGMT_OP_START_DISCOVERY
This make use of hci_cmd_sync_queue for MGMT_OP_START_DISCOVERY,
MGMT_OP_START_SERVICE_DISCOVERY and MGMT_OP_STOP_DISCOVERY to use
hci_cmd_sync_queue so they no longer depend on hdev->discov_update work
to send any commands.
Tested with:
tools/mgmt-tester -s "Start Discovery"
Test Summary
------------
Start Discovery - Not powered 1 Passed
Start Discovery - Invalid parameters 1 Passed
Start Discovery - Not supported 1 Passed
Start Discovery - Success 1 Passed
Start Discovery - Success 2 Passed
Start Discovery - Power Off 1 Passed
Start Discovery BREDR LE - (Ext Scan Enable) Passed
Start Discovery LE - (Ext Scan Enable) Passed
Start Discovery LE - (Ext Scan Param) Passed
Start Discovery - (2m, Scan Param) Passed
Start Discovery - (coded, Scan Param) Passed
Start Discovery - (1m, 2m, coded, Scan Param) Passed
LL Privacy - Start Discovery 1 (Disable RL) Passed
LL Privacy - Start Discovery 2 (Disable RL) Passed
Total: 14, Passed: 14 (100.0%), Failed: 0, Not Run: 0
tools/mgmt-tester -s "Start Service"
Test Summary
------------
Start Service Discovery - Not powered 1 Passed
Start Service Discovery - Invalid parameters 1 Passed
Start Service Discovery - Not supported 1 Passed
Start Service Discovery - Success 1 Passed
Start Service Discovery - Success 2 Passed
Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0
tools/mgmt-tester -s "Stop Discovery"
Test Summary
------------
Stop Discovery - Success 1 Passed
Stop Discovery - BR/EDR (Inquiry) Success 1 Passed
Stop Discovery - Rejected 1 Passed
Stop Discovery - Invalid parameters 1 Passed
Stop Discovery - (Ext Scan Disable) Passed
Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-28 02:58:45 +03:00
static int enable_advertising_sync ( struct hci_dev * hdev , void * data )
{
return hci_enable_advertising_sync ( hdev ) ;
}
int hci_enable_advertising ( struct hci_dev * hdev )
{
if ( ! hci_dev_test_flag ( hdev , HCI_ADVERTISING ) & &
list_empty ( & hdev - > adv_instances ) )
return 0 ;
return hci_cmd_sync_queue ( hdev , enable_advertising_sync , NULL , NULL ) ;
}
int hci_remove_ext_adv_instance_sync ( struct hci_dev * hdev , u8 instance ,
struct sock * sk )
Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 2
This make use of hci_cmd_sync_queue for the following MGMT commands:
Add Advertising
Remove Advertising
Add Extended Advertising Parameters
Add Extended Advertising Data
mgmt-tester -s "Add Advertising"
Test Summary
------------
Add Advertising - Failure: LE off Passed
Add Advertising - Invalid Params 1 (AD too long) Passed
Add Advertising - Invalid Params 2 (Malformed len) Passed
Add Advertising - Invalid Params 3 (Malformed len) Passed
Add Advertising - Invalid Params 4 (Malformed len) Passed
Add Advertising - Invalid Params 5 (AD too long) Passed
Add Advertising - Invalid Params 6 (ScRsp too long) Passed
Add Advertising - Invalid Params 7 (Malformed len) Passed
Add Advertising - Invalid Params 8 (Malformed len) Passed
Add Advertising - Invalid Params 9 (Malformed len) Passed
Add Advertising - Invalid Params 10 (ScRsp too long) Passed
Add Advertising - Rejected (Timeout, !Powered) Passed
Add Advertising - Success 1 (Powered, Add Adv Inst) Passed
Add Advertising - Success 2 (!Powered, Add Adv Inst) Passed
Add Advertising - Success 3 (!Powered, Adv Enable) Passed
Add Advertising - Success 4 (Set Adv on override) Passed
Add Advertising - Success 5 (Set Adv off override) Passed
Add Advertising - Success 6 (Scan Rsp Dta, Adv ok) Passed
Add Advertising - Success 7 (Scan Rsp Dta, Scan ok) Passed
Add Advertising - Success 8 (Connectable Flag) Passed
Add Advertising - Success 9 (General Discov Flag) Passed
Add Advertising - Success 10 (Limited Discov Flag) Passed
Add Advertising - Success 11 (Managed Flags) Passed
Add Advertising - Success 12 (TX Power Flag) Passed
Add Advertising - Success 13 (ADV_SCAN_IND) Passed
Add Advertising - Success 14 (ADV_NONCONN_IND) Passed
Add Advertising - Success 15 (ADV_IND) Passed
Add Advertising - Success 16 (Connectable -> on) Passed
Add Advertising - Success 17 (Connectable -> off) Passed
Add Advertising - Success 18 (Power -> off, Remove) Passed
Add Advertising - Success 19 (Power -> off, Keep) Passed
Add Advertising - Success 20 (Add Adv override) Passed
Add Advertising - Success 21 (Timeout expires) Passed
Add Advertising - Success 22 (LE -> off, Remove) Passed
Add Advertising - Success (Empty ScRsp) Passed
Add Advertising - Success (ScRsp only) Passed
Add Advertising - Invalid Params (ScRsp too long) Passed
Add Advertising - Success (ScRsp appear) Passed
Add Advertising - Invalid Params (ScRsp appear long) Passed
Add Advertising - Success (Appear is null) Passed
Add Advertising - Success (Name is null) Passed
Add Advertising - Success (Complete name) Passed
Add Advertising - Success (Shortened name) Passed
Add Advertising - Success (Short name) Passed
Add Advertising - Success (Name + data) Passed
Add Advertising - Invalid Params (Name + data) Passed
Add Advertising - Success (Name+data+appear) Passed
Total: 47, Passed: 47 (100.0%), Failed: 0, Not Run: 0
Overall execution time: 2.17 seconds
mgmt-tester -s "Remove Advertising"
Test Summary
------------
Remove Advertising - Invalid Params 1 Passed
Remove Advertising - Success 1 Passed
Remove Advertising - Success 2 Passed
Total: 3, Passed: 3 (100.0%), Failed: 0, Not Run: 0
Overall execution time: 0.0585 seconds
mgmt-tester -s "Ext Adv MGMT Params"
Test Summary:
------------
Ext Adv MGMT Params - Unpowered Passed
Ext Adv MGMT Params - Invalid parameters Passed
Ext Adv MGMT Params - Success Passed
Ext Adv MGMT Params - (5.0) Success Passed
Total: 4, Passed: 4 (100.0%), Failed: 0, Not Run: 0
Overall execution time: 0.0746 seconds
mgmt-tester -s "Ext Adv MGMT -"
Test Summary
------------
Ext Adv MGMT - Data set without Params Passed
Ext Adv MGMT - AD Data (5.0) Invalid parameters Passed
Ext Adv MGMT - AD Data (5.0) Success Passed
Ext Adv MGMT - AD Scan Response (5.0) Success Passed
Total: 4, Passed: 4 (100.0%), Failed: 0, Not Run: 0
Overall execution time: 0.0805 seconds
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-28 02:58:40 +03:00
{
int err ;
if ( ! ext_adv_capable ( hdev ) )
return 0 ;
err = hci_disable_ext_adv_instance_sync ( hdev , instance ) ;
if ( err )
return err ;
/* If request specifies an instance that doesn't exist, fail */
if ( instance > 0 & & ! hci_find_adv_instance ( hdev , instance ) )
return - EINVAL ;
return __hci_cmd_sync_status_sk ( hdev , HCI_OP_LE_REMOVE_ADV_SET ,
sizeof ( instance ) , & instance , 0 ,
HCI_CMD_TIMEOUT , sk ) ;
}
static void cancel_adv_timeout ( struct hci_dev * hdev )
{
if ( hdev - > adv_instance_timeout ) {
hdev - > adv_instance_timeout = 0 ;
cancel_delayed_work ( & hdev - > adv_instance_expire ) ;
}
}
static int hci_set_ext_adv_data_sync ( struct hci_dev * hdev , u8 instance )
{
struct {
struct hci_cp_le_set_ext_adv_data cp ;
u8 data [ HCI_MAX_EXT_AD_LENGTH ] ;
} pdu ;
u8 len ;
memset ( & pdu , 0 , sizeof ( pdu ) ) ;
len = eir_create_adv_data ( hdev , instance , pdu . data ) ;
/* There's nothing to do if the data hasn't changed */
if ( hdev - > adv_data_len = = len & &
memcmp ( pdu . data , hdev - > adv_data , len ) = = 0 )
return 0 ;
memcpy ( hdev - > adv_data , pdu . data , len ) ;
hdev - > adv_data_len = len ;
pdu . cp . length = len ;
pdu . cp . handle = instance ;
pdu . cp . operation = LE_SET_ADV_DATA_OP_COMPLETE ;
pdu . cp . frag_pref = LE_SET_ADV_DATA_NO_FRAG ;
return __hci_cmd_sync_status ( hdev , HCI_OP_LE_SET_EXT_ADV_DATA ,
sizeof ( pdu . cp ) + len , & pdu . cp ,
HCI_CMD_TIMEOUT ) ;
}
static int hci_set_adv_data_sync ( struct hci_dev * hdev , u8 instance )
{
struct hci_cp_le_set_adv_data cp ;
u8 len ;
memset ( & cp , 0 , sizeof ( cp ) ) ;
len = eir_create_adv_data ( hdev , instance , cp . data ) ;
/* There's nothing to do if the data hasn't changed */
if ( hdev - > adv_data_len = = len & &
memcmp ( cp . data , hdev - > adv_data , len ) = = 0 )
return 0 ;
memcpy ( hdev - > adv_data , cp . data , sizeof ( cp . data ) ) ;
hdev - > adv_data_len = len ;
cp . length = len ;
return __hci_cmd_sync_status ( hdev , HCI_OP_LE_SET_ADV_DATA ,
sizeof ( cp ) , & cp , HCI_CMD_TIMEOUT ) ;
}
int hci_update_adv_data_sync ( struct hci_dev * hdev , u8 instance )
{
if ( ! hci_dev_test_flag ( hdev , HCI_LE_ENABLED ) )
return 0 ;
if ( ext_adv_capable ( hdev ) )
return hci_set_ext_adv_data_sync ( hdev , instance ) ;
return hci_set_adv_data_sync ( hdev , instance ) ;
}
int hci_schedule_adv_instance_sync ( struct hci_dev * hdev , u8 instance ,
bool force )
{
struct adv_info * adv = NULL ;
u16 timeout ;
2021-10-28 02:58:44 +03:00
if ( hci_dev_test_flag ( hdev , HCI_ADVERTISING ) & & ! ext_adv_capable ( hdev ) )
Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 2
This make use of hci_cmd_sync_queue for the following MGMT commands:
Add Advertising
Remove Advertising
Add Extended Advertising Parameters
Add Extended Advertising Data
mgmt-tester -s "Add Advertising"
Test Summary
------------
Add Advertising - Failure: LE off Passed
Add Advertising - Invalid Params 1 (AD too long) Passed
Add Advertising - Invalid Params 2 (Malformed len) Passed
Add Advertising - Invalid Params 3 (Malformed len) Passed
Add Advertising - Invalid Params 4 (Malformed len) Passed
Add Advertising - Invalid Params 5 (AD too long) Passed
Add Advertising - Invalid Params 6 (ScRsp too long) Passed
Add Advertising - Invalid Params 7 (Malformed len) Passed
Add Advertising - Invalid Params 8 (Malformed len) Passed
Add Advertising - Invalid Params 9 (Malformed len) Passed
Add Advertising - Invalid Params 10 (ScRsp too long) Passed
Add Advertising - Rejected (Timeout, !Powered) Passed
Add Advertising - Success 1 (Powered, Add Adv Inst) Passed
Add Advertising - Success 2 (!Powered, Add Adv Inst) Passed
Add Advertising - Success 3 (!Powered, Adv Enable) Passed
Add Advertising - Success 4 (Set Adv on override) Passed
Add Advertising - Success 5 (Set Adv off override) Passed
Add Advertising - Success 6 (Scan Rsp Dta, Adv ok) Passed
Add Advertising - Success 7 (Scan Rsp Dta, Scan ok) Passed
Add Advertising - Success 8 (Connectable Flag) Passed
Add Advertising - Success 9 (General Discov Flag) Passed
Add Advertising - Success 10 (Limited Discov Flag) Passed
Add Advertising - Success 11 (Managed Flags) Passed
Add Advertising - Success 12 (TX Power Flag) Passed
Add Advertising - Success 13 (ADV_SCAN_IND) Passed
Add Advertising - Success 14 (ADV_NONCONN_IND) Passed
Add Advertising - Success 15 (ADV_IND) Passed
Add Advertising - Success 16 (Connectable -> on) Passed
Add Advertising - Success 17 (Connectable -> off) Passed
Add Advertising - Success 18 (Power -> off, Remove) Passed
Add Advertising - Success 19 (Power -> off, Keep) Passed
Add Advertising - Success 20 (Add Adv override) Passed
Add Advertising - Success 21 (Timeout expires) Passed
Add Advertising - Success 22 (LE -> off, Remove) Passed
Add Advertising - Success (Empty ScRsp) Passed
Add Advertising - Success (ScRsp only) Passed
Add Advertising - Invalid Params (ScRsp too long) Passed
Add Advertising - Success (ScRsp appear) Passed
Add Advertising - Invalid Params (ScRsp appear long) Passed
Add Advertising - Success (Appear is null) Passed
Add Advertising - Success (Name is null) Passed
Add Advertising - Success (Complete name) Passed
Add Advertising - Success (Shortened name) Passed
Add Advertising - Success (Short name) Passed
Add Advertising - Success (Name + data) Passed
Add Advertising - Invalid Params (Name + data) Passed
Add Advertising - Success (Name+data+appear) Passed
Total: 47, Passed: 47 (100.0%), Failed: 0, Not Run: 0
Overall execution time: 2.17 seconds
mgmt-tester -s "Remove Advertising"
Test Summary
------------
Remove Advertising - Invalid Params 1 Passed
Remove Advertising - Success 1 Passed
Remove Advertising - Success 2 Passed
Total: 3, Passed: 3 (100.0%), Failed: 0, Not Run: 0
Overall execution time: 0.0585 seconds
mgmt-tester -s "Ext Adv MGMT Params"
Test Summary:
------------
Ext Adv MGMT Params - Unpowered Passed
Ext Adv MGMT Params - Invalid parameters Passed
Ext Adv MGMT Params - Success Passed
Ext Adv MGMT Params - (5.0) Success Passed
Total: 4, Passed: 4 (100.0%), Failed: 0, Not Run: 0
Overall execution time: 0.0746 seconds
mgmt-tester -s "Ext Adv MGMT -"
Test Summary
------------
Ext Adv MGMT - Data set without Params Passed
Ext Adv MGMT - AD Data (5.0) Invalid parameters Passed
Ext Adv MGMT - AD Data (5.0) Success Passed
Ext Adv MGMT - AD Scan Response (5.0) Success Passed
Total: 4, Passed: 4 (100.0%), Failed: 0, Not Run: 0
Overall execution time: 0.0805 seconds
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-28 02:58:40 +03:00
return - EPERM ;
if ( hdev - > adv_instance_timeout )
return - EBUSY ;
adv = hci_find_adv_instance ( hdev , instance ) ;
if ( ! adv )
return - ENOENT ;
/* A zero timeout means unlimited advertising. As long as there is
* only one instance , duration should be ignored . We still set a timeout
* in case further instances are being added later on .
*
* If the remaining lifetime of the instance is more than the duration
* then the timeout corresponds to the duration , otherwise it will be
* reduced to the remaining instance lifetime .
*/
if ( adv - > timeout = = 0 | | adv - > duration < = adv - > remaining_time )
timeout = adv - > duration ;
else
timeout = adv - > remaining_time ;
/* The remaining time is being reduced unless the instance is being
* advertised without time limit .
*/
if ( adv - > timeout )
adv - > remaining_time = adv - > remaining_time - timeout ;
/* Only use work for scheduling instances with legacy advertising */
if ( ! ext_adv_capable ( hdev ) ) {
hdev - > adv_instance_timeout = timeout ;
queue_delayed_work ( hdev - > req_workqueue ,
& hdev - > adv_instance_expire ,
msecs_to_jiffies ( timeout * 1000 ) ) ;
}
/* If we're just re-scheduling the same instance again then do not
* execute any HCI commands . This happens when a single instance is
* being advertised .
*/
if ( ! force & & hdev - > cur_adv_instance = = instance & &
hci_dev_test_flag ( hdev , HCI_LE_ADV ) )
return 0 ;
hdev - > cur_adv_instance = instance ;
return hci_start_adv_sync ( hdev , instance ) ;
}
static int hci_clear_adv_sets_sync ( struct hci_dev * hdev , struct sock * sk )
{
int err ;
if ( ! ext_adv_capable ( hdev ) )
return 0 ;
/* Disable instance 0x00 to disable all instances */
err = hci_disable_ext_adv_instance_sync ( hdev , 0x00 ) ;
if ( err )
return err ;
return __hci_cmd_sync_status_sk ( hdev , HCI_OP_LE_CLEAR_ADV_SETS ,
0 , NULL , 0 , HCI_CMD_TIMEOUT , sk ) ;
}
static int hci_clear_adv_sync ( struct hci_dev * hdev , struct sock * sk , bool force )
{
struct adv_info * adv , * n ;
if ( ext_adv_capable ( hdev ) )
/* Remove all existing sets */
return hci_clear_adv_sets_sync ( hdev , sk ) ;
/* This is safe as long as there is no command send while the lock is
* held .
*/
hci_dev_lock ( hdev ) ;
/* Cleanup non-ext instances */
list_for_each_entry_safe ( adv , n , & hdev - > adv_instances , list ) {
u8 instance = adv - > instance ;
int err ;
if ( ! ( force | | adv - > timeout ) )
continue ;
err = hci_remove_adv_instance ( hdev , instance ) ;
if ( ! err )
mgmt_advertising_removed ( sk , hdev , instance ) ;
}
hci_dev_unlock ( hdev ) ;
return 0 ;
}
static int hci_remove_adv_sync ( struct hci_dev * hdev , u8 instance ,
struct sock * sk )
{
int err ;
/* If we use extended advertising, instance has to be removed first. */
if ( ext_adv_capable ( hdev ) )
return hci_remove_ext_adv_instance_sync ( hdev , instance , sk ) ;
/* This is safe as long as there is no command send while the lock is
* held .
*/
hci_dev_lock ( hdev ) ;
err = hci_remove_adv_instance ( hdev , instance ) ;
if ( ! err )
mgmt_advertising_removed ( sk , hdev , instance ) ;
hci_dev_unlock ( hdev ) ;
return err ;
}
/* For a single instance:
* - force = = true : The instance will be removed even when its remaining
* lifetime is not zero .
* - force = = false : the instance will be deactivated but kept stored unless
* the remaining lifetime is zero .
*
* For instance = = 0x00 :
* - force = = true : All instances will be removed regardless of their timeout
* setting .
* - force = = false : Only instances that have a timeout will be removed .
*/
int hci_remove_advertising_sync ( struct hci_dev * hdev , struct sock * sk ,
u8 instance , bool force )
{
struct adv_info * next = NULL ;
int err ;
/* Cancel any timeout concerning the removed instance(s). */
if ( ! instance | | hdev - > cur_adv_instance = = instance )
cancel_adv_timeout ( hdev ) ;
/* Get the next instance to advertise BEFORE we remove
* the current one . This can be the same instance again
* if there is only one instance .
*/
if ( hdev - > cur_adv_instance = = instance )
next = hci_get_next_instance ( hdev , instance ) ;
if ( ! instance ) {
err = hci_clear_adv_sync ( hdev , sk , force ) ;
if ( err )
return err ;
} else {
struct adv_info * adv = hci_find_adv_instance ( hdev , instance ) ;
if ( force | | ( adv & & adv - > timeout & & ! adv - > remaining_time ) ) {
/* Don't advertise a removed instance. */
if ( next & & next - > instance = = instance )
next = NULL ;
err = hci_remove_adv_sync ( hdev , instance , sk ) ;
if ( err )
return err ;
}
}
if ( ! hdev_is_powered ( hdev ) | | hci_dev_test_flag ( hdev , HCI_ADVERTISING ) )
return 0 ;
if ( next & & ! ext_adv_capable ( hdev ) )
hci_schedule_adv_instance_sync ( hdev , next - > instance , false ) ;
return 0 ;
}
int hci_disable_advertising_sync ( struct hci_dev * hdev )
{
u8 enable = 0x00 ;
2021-10-28 02:58:42 +03:00
/* If controller is not advertising we are done. */
if ( ! hci_dev_test_flag ( hdev , HCI_LE_ADV ) )
return 0 ;
Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 2
This make use of hci_cmd_sync_queue for the following MGMT commands:
Add Advertising
Remove Advertising
Add Extended Advertising Parameters
Add Extended Advertising Data
mgmt-tester -s "Add Advertising"
Test Summary
------------
Add Advertising - Failure: LE off Passed
Add Advertising - Invalid Params 1 (AD too long) Passed
Add Advertising - Invalid Params 2 (Malformed len) Passed
Add Advertising - Invalid Params 3 (Malformed len) Passed
Add Advertising - Invalid Params 4 (Malformed len) Passed
Add Advertising - Invalid Params 5 (AD too long) Passed
Add Advertising - Invalid Params 6 (ScRsp too long) Passed
Add Advertising - Invalid Params 7 (Malformed len) Passed
Add Advertising - Invalid Params 8 (Malformed len) Passed
Add Advertising - Invalid Params 9 (Malformed len) Passed
Add Advertising - Invalid Params 10 (ScRsp too long) Passed
Add Advertising - Rejected (Timeout, !Powered) Passed
Add Advertising - Success 1 (Powered, Add Adv Inst) Passed
Add Advertising - Success 2 (!Powered, Add Adv Inst) Passed
Add Advertising - Success 3 (!Powered, Adv Enable) Passed
Add Advertising - Success 4 (Set Adv on override) Passed
Add Advertising - Success 5 (Set Adv off override) Passed
Add Advertising - Success 6 (Scan Rsp Dta, Adv ok) Passed
Add Advertising - Success 7 (Scan Rsp Dta, Scan ok) Passed
Add Advertising - Success 8 (Connectable Flag) Passed
Add Advertising - Success 9 (General Discov Flag) Passed
Add Advertising - Success 10 (Limited Discov Flag) Passed
Add Advertising - Success 11 (Managed Flags) Passed
Add Advertising - Success 12 (TX Power Flag) Passed
Add Advertising - Success 13 (ADV_SCAN_IND) Passed
Add Advertising - Success 14 (ADV_NONCONN_IND) Passed
Add Advertising - Success 15 (ADV_IND) Passed
Add Advertising - Success 16 (Connectable -> on) Passed
Add Advertising - Success 17 (Connectable -> off) Passed
Add Advertising - Success 18 (Power -> off, Remove) Passed
Add Advertising - Success 19 (Power -> off, Keep) Passed
Add Advertising - Success 20 (Add Adv override) Passed
Add Advertising - Success 21 (Timeout expires) Passed
Add Advertising - Success 22 (LE -> off, Remove) Passed
Add Advertising - Success (Empty ScRsp) Passed
Add Advertising - Success (ScRsp only) Passed
Add Advertising - Invalid Params (ScRsp too long) Passed
Add Advertising - Success (ScRsp appear) Passed
Add Advertising - Invalid Params (ScRsp appear long) Passed
Add Advertising - Success (Appear is null) Passed
Add Advertising - Success (Name is null) Passed
Add Advertising - Success (Complete name) Passed
Add Advertising - Success (Shortened name) Passed
Add Advertising - Success (Short name) Passed
Add Advertising - Success (Name + data) Passed
Add Advertising - Invalid Params (Name + data) Passed
Add Advertising - Success (Name+data+appear) Passed
Total: 47, Passed: 47 (100.0%), Failed: 0, Not Run: 0
Overall execution time: 2.17 seconds
mgmt-tester -s "Remove Advertising"
Test Summary
------------
Remove Advertising - Invalid Params 1 Passed
Remove Advertising - Success 1 Passed
Remove Advertising - Success 2 Passed
Total: 3, Passed: 3 (100.0%), Failed: 0, Not Run: 0
Overall execution time: 0.0585 seconds
mgmt-tester -s "Ext Adv MGMT Params"
Test Summary:
------------
Ext Adv MGMT Params - Unpowered Passed
Ext Adv MGMT Params - Invalid parameters Passed
Ext Adv MGMT Params - Success Passed
Ext Adv MGMT Params - (5.0) Success Passed
Total: 4, Passed: 4 (100.0%), Failed: 0, Not Run: 0
Overall execution time: 0.0746 seconds
mgmt-tester -s "Ext Adv MGMT -"
Test Summary
------------
Ext Adv MGMT - Data set without Params Passed
Ext Adv MGMT - AD Data (5.0) Invalid parameters Passed
Ext Adv MGMT - AD Data (5.0) Success Passed
Ext Adv MGMT - AD Scan Response (5.0) Success Passed
Total: 4, Passed: 4 (100.0%), Failed: 0, Not Run: 0
Overall execution time: 0.0805 seconds
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-28 02:58:40 +03:00
if ( ext_adv_capable ( hdev ) )
return hci_disable_ext_adv_instance_sync ( hdev , 0x00 ) ;
return __hci_cmd_sync_status ( hdev , HCI_OP_LE_SET_ADV_ENABLE ,
sizeof ( enable ) , & enable , HCI_CMD_TIMEOUT ) ;
}
2021-10-28 02:58:41 +03:00
static int hci_le_set_ext_scan_enable_sync ( struct hci_dev * hdev , u8 val ,
u8 filter_dup )
{
struct hci_cp_le_set_ext_scan_enable cp ;
memset ( & cp , 0 , sizeof ( cp ) ) ;
cp . enable = val ;
cp . filter_dup = filter_dup ;
return __hci_cmd_sync_status ( hdev , HCI_OP_LE_SET_EXT_SCAN_ENABLE ,
sizeof ( cp ) , & cp , HCI_CMD_TIMEOUT ) ;
}
static int hci_le_set_scan_enable_sync ( struct hci_dev * hdev , u8 val ,
u8 filter_dup )
{
struct hci_cp_le_set_scan_enable cp ;
if ( use_ext_scan ( hdev ) )
return hci_le_set_ext_scan_enable_sync ( hdev , val , filter_dup ) ;
memset ( & cp , 0 , sizeof ( cp ) ) ;
cp . enable = val ;
cp . filter_dup = filter_dup ;
return __hci_cmd_sync_status ( hdev , HCI_OP_LE_SET_SCAN_ENABLE ,
sizeof ( cp ) , & cp , HCI_CMD_TIMEOUT ) ;
}
static int hci_le_set_addr_resolution_enable_sync ( struct hci_dev * hdev , u8 val )
{
2021-10-28 02:58:42 +03:00
if ( ! use_ll_privacy ( hdev ) )
return 0 ;
/* If controller is not/already resolving we are done. */
if ( val = = hci_dev_test_flag ( hdev , HCI_LL_RPA_RESOLUTION ) )
2021-10-28 02:58:41 +03:00
return 0 ;
return __hci_cmd_sync_status ( hdev , HCI_OP_LE_SET_ADDR_RESOLV_ENABLE ,
sizeof ( val ) , & val , HCI_CMD_TIMEOUT ) ;
}
2021-10-28 02:58:42 +03:00
int hci_scan_disable_sync ( struct hci_dev * hdev )
2021-10-28 02:58:41 +03:00
{
int err ;
/* If controller is not scanning we are done. */
if ( ! hci_dev_test_flag ( hdev , HCI_LE_SCAN ) )
return 0 ;
if ( hdev - > scanning_paused ) {
bt_dev_dbg ( hdev , " Scanning is paused for suspend " ) ;
return 0 ;
}
if ( hdev - > suspended )
set_bit ( SUSPEND_SCAN_DISABLE , hdev - > suspend_tasks ) ;
err = hci_le_set_scan_enable_sync ( hdev , LE_SCAN_DISABLE , 0x00 ) ;
if ( err ) {
bt_dev_err ( hdev , " Unable to disable scanning: %d " , err ) ;
return err ;
}
return err ;
}
static bool scan_use_rpa ( struct hci_dev * hdev )
{
return hci_dev_test_flag ( hdev , HCI_PRIVACY ) ;
}
static void hci_start_interleave_scan ( struct hci_dev * hdev )
{
hdev - > interleave_scan_state = INTERLEAVE_SCAN_NO_FILTER ;
queue_delayed_work ( hdev - > req_workqueue ,
& hdev - > interleave_scan , 0 ) ;
}
static bool is_interleave_scanning ( struct hci_dev * hdev )
{
return hdev - > interleave_scan_state ! = INTERLEAVE_SCAN_NONE ;
}
static void cancel_interleave_scan ( struct hci_dev * hdev )
{
bt_dev_dbg ( hdev , " cancelling interleave scan " ) ;
cancel_delayed_work_sync ( & hdev - > interleave_scan ) ;
hdev - > interleave_scan_state = INTERLEAVE_SCAN_NONE ;
}
/* Return true if interleave_scan wasn't started until exiting this function,
* otherwise , return false
*/
static bool hci_update_interleaved_scan_sync ( struct hci_dev * hdev )
{
/* Do interleaved scan only if all of the following are true:
* - There is at least one ADV monitor
* - At least one pending LE connection or one device to be scanned for
* - Monitor offloading is not supported
* If so , we should alternate between allowlist scan and one without
* any filters to save power .
*/
bool use_interleaving = hci_is_adv_monitoring ( hdev ) & &
! ( list_empty ( & hdev - > pend_le_conns ) & &
list_empty ( & hdev - > pend_le_reports ) ) & &
hci_get_adv_monitor_offload_ext ( hdev ) = =
HCI_ADV_MONITOR_EXT_NONE ;
bool is_interleaving = is_interleave_scanning ( hdev ) ;
if ( use_interleaving & & ! is_interleaving ) {
hci_start_interleave_scan ( hdev ) ;
bt_dev_dbg ( hdev , " starting interleave scan " ) ;
return true ;
}
if ( ! use_interleaving & & is_interleaving )
cancel_interleave_scan ( hdev ) ;
return false ;
}
/* Removes connection to resolve list if needed.*/
static int hci_le_del_resolve_list_sync ( struct hci_dev * hdev ,
bdaddr_t * bdaddr , u8 bdaddr_type )
{
struct hci_cp_le_del_from_resolv_list cp ;
struct bdaddr_list_with_irk * entry ;
2021-10-28 02:58:42 +03:00
if ( ! use_ll_privacy ( hdev ) )
2021-10-28 02:58:41 +03:00
return 0 ;
/* Check if the IRK has been programmed */
entry = hci_bdaddr_list_lookup_with_irk ( & hdev - > le_resolv_list , bdaddr ,
bdaddr_type ) ;
if ( ! entry )
return 0 ;
cp . bdaddr_type = bdaddr_type ;
bacpy ( & cp . bdaddr , bdaddr ) ;
return __hci_cmd_sync_status ( hdev , HCI_OP_LE_DEL_FROM_RESOLV_LIST ,
sizeof ( cp ) , & cp , HCI_CMD_TIMEOUT ) ;
}
static int hci_le_del_accept_list_sync ( struct hci_dev * hdev ,
bdaddr_t * bdaddr , u8 bdaddr_type )
{
struct hci_cp_le_del_from_accept_list cp ;
int err ;
/* Check if device is on accept list before removing it */
if ( ! hci_bdaddr_list_lookup ( & hdev - > le_accept_list , bdaddr , bdaddr_type ) )
return 0 ;
cp . bdaddr_type = bdaddr_type ;
bacpy ( & cp . bdaddr , bdaddr ) ;
2021-10-28 02:58:42 +03:00
/* Ignore errors when removing from resolving list as that is likely
* that the device was never added .
*/
hci_le_del_resolve_list_sync ( hdev , & cp . bdaddr , cp . bdaddr_type ) ;
2021-10-28 02:58:41 +03:00
err = __hci_cmd_sync_status ( hdev , HCI_OP_LE_DEL_FROM_ACCEPT_LIST ,
sizeof ( cp ) , & cp , HCI_CMD_TIMEOUT ) ;
if ( err ) {
bt_dev_err ( hdev , " Unable to remove from allow list: %d " , err ) ;
return err ;
}
bt_dev_dbg ( hdev , " Remove %pMR (0x%x) from allow list " , & cp . bdaddr ,
cp . bdaddr_type ) ;
2021-10-28 02:58:42 +03:00
return 0 ;
2021-10-28 02:58:41 +03:00
}
2021-10-28 02:58:44 +03:00
/* Adds connection to resolve list if needed.
* Setting params to NULL programs local hdev - > irk
*/
2021-10-28 02:58:41 +03:00
static int hci_le_add_resolve_list_sync ( struct hci_dev * hdev ,
struct hci_conn_params * params )
{
struct hci_cp_le_add_to_resolv_list cp ;
struct smp_irk * irk ;
struct bdaddr_list_with_irk * entry ;
2021-10-28 02:58:42 +03:00
if ( ! use_ll_privacy ( hdev ) )
2021-10-28 02:58:41 +03:00
return 0 ;
2021-10-28 02:58:44 +03:00
/* Attempt to program local identity address, type and irk if params is
* NULL .
*/
if ( ! params ) {
if ( ! hci_dev_test_flag ( hdev , HCI_PRIVACY ) )
return 0 ;
hci_copy_identity_address ( hdev , & cp . bdaddr , & cp . bdaddr_type ) ;
memcpy ( cp . peer_irk , hdev - > irk , 16 ) ;
goto done ;
}
2021-10-28 02:58:41 +03:00
irk = hci_find_irk_by_addr ( hdev , & params - > addr , params - > addr_type ) ;
if ( ! irk )
return 0 ;
/* Check if the IK has _not_ been programmed yet. */
entry = hci_bdaddr_list_lookup_with_irk ( & hdev - > le_resolv_list ,
& params - > addr ,
params - > addr_type ) ;
if ( entry )
return 0 ;
cp . bdaddr_type = params - > addr_type ;
bacpy ( & cp . bdaddr , & params - > addr ) ;
memcpy ( cp . peer_irk , irk - > val , 16 ) ;
2021-10-28 02:58:44 +03:00
done :
2021-10-28 02:58:41 +03:00
if ( hci_dev_test_flag ( hdev , HCI_PRIVACY ) )
memcpy ( cp . local_irk , hdev - > irk , 16 ) ;
else
memset ( cp . local_irk , 0 , 16 ) ;
return __hci_cmd_sync_status ( hdev , HCI_OP_LE_ADD_TO_RESOLV_LIST ,
sizeof ( cp ) , & cp , HCI_CMD_TIMEOUT ) ;
}
/* Adds connection to allow list if needed, if the device uses RPA (has IRK)
* this attempts to program the device in the resolving list as well .
*/
static int hci_le_add_accept_list_sync ( struct hci_dev * hdev ,
struct hci_conn_params * params ,
2021-10-28 02:58:42 +03:00
u8 * num_entries )
2021-10-28 02:58:41 +03:00
{
struct hci_cp_le_add_to_accept_list cp ;
int err ;
/* Already in accept list */
if ( hci_bdaddr_list_lookup ( & hdev - > le_accept_list , & params - > addr ,
params - > addr_type ) )
return 0 ;
/* Select filter policy to accept all advertising */
if ( * num_entries > = hdev - > le_accept_list_size )
return - ENOSPC ;
/* Accept list can not be used with RPAs */
2021-10-28 02:58:42 +03:00
if ( ! use_ll_privacy ( hdev ) & &
2021-10-28 02:58:41 +03:00
hci_find_irk_by_addr ( hdev , & params - > addr , params - > addr_type ) ) {
return - EINVAL ;
}
/* During suspend, only wakeable devices can be in acceptlist */
if ( hdev - > suspended & & ! hci_conn_test_flag ( HCI_CONN_FLAG_REMOTE_WAKEUP ,
params - > current_flags ) )
return 0 ;
2021-10-28 02:58:42 +03:00
/* Attempt to program the device in the resolving list first to avoid
* having to rollback in case it fails since the resolving list is
* dynamic it can probably be smaller than the accept list .
*/
err = hci_le_add_resolve_list_sync ( hdev , params ) ;
if ( err ) {
bt_dev_err ( hdev , " Unable to add to resolve list: %d " , err ) ;
return err ;
}
2021-10-28 02:58:41 +03:00
* num_entries + = 1 ;
cp . bdaddr_type = params - > addr_type ;
bacpy ( & cp . bdaddr , & params - > addr ) ;
err = __hci_cmd_sync_status ( hdev , HCI_OP_LE_ADD_TO_ACCEPT_LIST ,
sizeof ( cp ) , & cp , HCI_CMD_TIMEOUT ) ;
if ( err ) {
bt_dev_err ( hdev , " Unable to add to allow list: %d " , err ) ;
2021-10-28 02:58:42 +03:00
/* Rollback the device from the resolving list */
hci_le_del_resolve_list_sync ( hdev , & cp . bdaddr , cp . bdaddr_type ) ;
2021-10-28 02:58:41 +03:00
return err ;
}
bt_dev_dbg ( hdev , " Add %pMR (0x%x) to allow list " , & cp . bdaddr ,
cp . bdaddr_type ) ;
2021-10-28 02:58:42 +03:00
return 0 ;
}
/* This function disables all advertising instances (including 0x00) */
static int hci_pause_advertising_sync ( struct hci_dev * hdev )
{
int err ;
/* If there are no instances or advertising has already been paused
* there is nothing to do .
*/
if ( ! hdev - > adv_instance_cnt | | hdev - > advertising_paused )
return 0 ;
bt_dev_dbg ( hdev , " Pausing advertising instances " ) ;
/* Call to disable any advertisements active on the controller.
* This will succeed even if no advertisements are configured .
*/
err = hci_disable_advertising_sync ( hdev ) ;
if ( err )
return err ;
/* If we are using software rotation, pause the loop */
if ( ! ext_adv_capable ( hdev ) )
cancel_adv_timeout ( hdev ) ;
hdev - > advertising_paused = true ;
return 0 ;
2021-10-28 02:58:41 +03:00
}
Bluetooth: hci_sync: Convert MGMT_OP_START_DISCOVERY
This make use of hci_cmd_sync_queue for MGMT_OP_START_DISCOVERY,
MGMT_OP_START_SERVICE_DISCOVERY and MGMT_OP_STOP_DISCOVERY to use
hci_cmd_sync_queue so they no longer depend on hdev->discov_update work
to send any commands.
Tested with:
tools/mgmt-tester -s "Start Discovery"
Test Summary
------------
Start Discovery - Not powered 1 Passed
Start Discovery - Invalid parameters 1 Passed
Start Discovery - Not supported 1 Passed
Start Discovery - Success 1 Passed
Start Discovery - Success 2 Passed
Start Discovery - Power Off 1 Passed
Start Discovery BREDR LE - (Ext Scan Enable) Passed
Start Discovery LE - (Ext Scan Enable) Passed
Start Discovery LE - (Ext Scan Param) Passed
Start Discovery - (2m, Scan Param) Passed
Start Discovery - (coded, Scan Param) Passed
Start Discovery - (1m, 2m, coded, Scan Param) Passed
LL Privacy - Start Discovery 1 (Disable RL) Passed
LL Privacy - Start Discovery 2 (Disable RL) Passed
Total: 14, Passed: 14 (100.0%), Failed: 0, Not Run: 0
tools/mgmt-tester -s "Start Service"
Test Summary
------------
Start Service Discovery - Not powered 1 Passed
Start Service Discovery - Invalid parameters 1 Passed
Start Service Discovery - Not supported 1 Passed
Start Service Discovery - Success 1 Passed
Start Service Discovery - Success 2 Passed
Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0
tools/mgmt-tester -s "Stop Discovery"
Test Summary
------------
Stop Discovery - Success 1 Passed
Stop Discovery - BR/EDR (Inquiry) Success 1 Passed
Stop Discovery - Rejected 1 Passed
Stop Discovery - Invalid parameters 1 Passed
Stop Discovery - (Ext Scan Disable) Passed
Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-28 02:58:45 +03:00
/* This function enables all user advertising instances (excluding 0x00) */
2021-10-28 02:58:42 +03:00
static int hci_resume_advertising_sync ( struct hci_dev * hdev )
{
struct adv_info * adv , * tmp ;
int err ;
/* If advertising has not been paused there is nothing to do. */
if ( ! hdev - > advertising_paused )
return 0 ;
bt_dev_dbg ( hdev , " Resuming advertising instances " ) ;
if ( ext_adv_capable ( hdev ) ) {
/* Call for each tracked instance to be re-enabled */
list_for_each_entry_safe ( adv , tmp , & hdev - > adv_instances , list ) {
err = hci_enable_ext_advertising_sync ( hdev ,
adv - > instance ) ;
if ( ! err )
continue ;
/* If the instance cannot be resumed remove it */
hci_remove_ext_adv_instance_sync ( hdev , adv - > instance ,
NULL ) ;
}
} else {
/* Schedule for most recent instance to be restarted and begin
* the software rotation loop
*/
err = hci_schedule_adv_instance_sync ( hdev ,
hdev - > cur_adv_instance ,
true ) ;
}
hdev - > advertising_paused = false ;
return err ;
}
/* Device must not be scanning when updating the accept list.
*
* Update is done using the following sequence :
*
* use_ll_privacy ( ( Disable Advertising ) - > Disable Resolving List ) - >
* Remove Devices From Accept List - >
* ( has IRK & & use_ll_privacy ( Remove Devices From Resolving List ) ) - >
* Add Devices to Accept List - >
* ( has IRK & & use_ll_privacy ( Remove Devices From Resolving List ) ) - >
* use_ll_privacy ( Enable Resolving List - > ( Enable Advertising ) ) - >
* Enable Scanning
*
* In case of failure advertising shall be restored to its original state and
* return would disable accept list since either accept or resolving list could
* not be programmed .
*
*/
2021-10-28 02:58:41 +03:00
static u8 hci_update_accept_list_sync ( struct hci_dev * hdev )
{
struct hci_conn_params * params ;
struct bdaddr_list * b , * t ;
u8 num_entries = 0 ;
bool pend_conn , pend_report ;
2021-10-28 02:58:42 +03:00
int err ;
/* Pause advertising if resolving list can be used as controllers are
* cannot accept resolving list modifications while advertising .
2021-10-28 02:58:41 +03:00
*/
2021-10-28 02:58:42 +03:00
if ( use_ll_privacy ( hdev ) ) {
err = hci_pause_advertising_sync ( hdev ) ;
if ( err ) {
bt_dev_err ( hdev , " pause advertising failed: %d " , err ) ;
return 0x00 ;
}
}
2021-10-28 02:58:41 +03:00
2021-10-28 02:58:42 +03:00
/* Disable address resolution while reprogramming accept list since
* devices that do have an IRK will be programmed in the resolving list
* when LL Privacy is enabled .
*/
err = hci_le_set_addr_resolution_enable_sync ( hdev , 0x00 ) ;
if ( err ) {
bt_dev_err ( hdev , " Unable to disable LL privacy: %d " , err ) ;
goto done ;
}
2021-10-28 02:58:41 +03:00
/* Go through the current accept list programmed into the
* controller one by one and check if that address is still
* in the list of pending connections or list of devices to
* report . If not present in either list , then remove it from
* the controller .
*/
list_for_each_entry_safe ( b , t , & hdev - > le_accept_list , list ) {
pend_conn = hci_pend_le_action_lookup ( & hdev - > pend_le_conns ,
& b - > bdaddr ,
b - > bdaddr_type ) ;
pend_report = hci_pend_le_action_lookup ( & hdev - > pend_le_reports ,
& b - > bdaddr ,
b - > bdaddr_type ) ;
/* If the device is not likely to connect or report,
* remove it from the acceptlist .
*/
if ( ! pend_conn & & ! pend_report ) {
hci_le_del_accept_list_sync ( hdev , & b - > bdaddr ,
b - > bdaddr_type ) ;
continue ;
}
num_entries + + ;
}
/* Since all no longer valid accept list entries have been
* removed , walk through the list of pending connections
* and ensure that any new device gets programmed into
* the controller .
*
* If the list of the devices is larger than the list of
* available accept list entries in the controller , then
* just abort and return filer policy value to not use the
* accept list .
*/
list_for_each_entry ( params , & hdev - > pend_le_conns , action ) {
2021-10-28 02:58:42 +03:00
err = hci_le_add_accept_list_sync ( hdev , params , & num_entries ) ;
if ( err )
goto done ;
2021-10-28 02:58:41 +03:00
}
/* After adding all new pending connections, walk through
* the list of pending reports and also add these to the
* accept list if there is still space . Abort if space runs out .
*/
list_for_each_entry ( params , & hdev - > pend_le_reports , action ) {
2021-10-28 02:58:42 +03:00
err = hci_le_add_accept_list_sync ( hdev , params , & num_entries ) ;
if ( err )
goto done ;
2021-10-28 02:58:41 +03:00
}
/* Use the allowlist unless the following conditions are all true:
* - We are not currently suspending
* - There are 1 or more ADV monitors registered and it ' s not offloaded
* - Interleaved scanning is not currently using the allowlist
*/
if ( ! idr_is_empty ( & hdev - > adv_monitors_idr ) & & ! hdev - > suspended & &
hci_get_adv_monitor_offload_ext ( hdev ) = = HCI_ADV_MONITOR_EXT_NONE & &
hdev - > interleave_scan_state ! = INTERLEAVE_SCAN_ALLOWLIST )
2021-10-28 02:58:42 +03:00
err = - EINVAL ;
done :
/* Enable address resolution when LL Privacy is enabled. */
err = hci_le_set_addr_resolution_enable_sync ( hdev , 0x01 ) ;
if ( err )
bt_dev_err ( hdev , " Unable to enable LL privacy: %d " , err ) ;
/* Resume advertising if it was paused */
if ( use_ll_privacy ( hdev ) )
hci_resume_advertising_sync ( hdev ) ;
2021-10-28 02:58:41 +03:00
/* Select filter policy to use accept list */
2021-10-28 02:58:42 +03:00
return err ? 0x00 : 0x01 ;
2021-10-28 02:58:41 +03:00
}
/* Returns true if an le connection is in the scanning state */
static inline bool hci_is_le_conn_scanning ( struct hci_dev * hdev )
{
struct hci_conn_hash * h = & hdev - > conn_hash ;
struct hci_conn * c ;
rcu_read_lock ( ) ;
list_for_each_entry_rcu ( c , & h - > list , list ) {
if ( c - > type = = LE_LINK & & c - > state = = BT_CONNECT & &
test_bit ( HCI_CONN_SCANNING , & c - > flags ) ) {
rcu_read_unlock ( ) ;
return true ;
}
}
rcu_read_unlock ( ) ;
return false ;
}
static int hci_le_set_ext_scan_param_sync ( struct hci_dev * hdev , u8 type ,
u16 interval , u16 window ,
u8 own_addr_type , u8 filter_policy )
{
struct hci_cp_le_set_ext_scan_params * cp ;
struct hci_cp_le_scan_phy_params * phy ;
u8 data [ sizeof ( * cp ) + sizeof ( * phy ) * 2 ] ;
u8 num_phy = 0 ;
cp = ( void * ) data ;
phy = ( void * ) cp - > data ;
memset ( data , 0 , sizeof ( data ) ) ;
cp - > own_addr_type = own_addr_type ;
cp - > filter_policy = filter_policy ;
if ( scan_1m ( hdev ) | | scan_2m ( hdev ) ) {
cp - > scanning_phys | = LE_SCAN_PHY_1M ;
phy - > type = type ;
phy - > interval = cpu_to_le16 ( interval ) ;
phy - > window = cpu_to_le16 ( window ) ;
num_phy + + ;
phy + + ;
}
if ( scan_coded ( hdev ) ) {
cp - > scanning_phys | = LE_SCAN_PHY_CODED ;
phy - > type = type ;
phy - > interval = cpu_to_le16 ( interval ) ;
phy - > window = cpu_to_le16 ( window ) ;
num_phy + + ;
phy + + ;
}
return __hci_cmd_sync_status ( hdev , HCI_OP_LE_SET_EXT_SCAN_PARAMS ,
sizeof ( * cp ) + sizeof ( * phy ) * num_phy ,
data , HCI_CMD_TIMEOUT ) ;
}
static int hci_le_set_scan_param_sync ( struct hci_dev * hdev , u8 type ,
u16 interval , u16 window ,
u8 own_addr_type , u8 filter_policy )
{
struct hci_cp_le_set_scan_param cp ;
if ( use_ext_scan ( hdev ) )
return hci_le_set_ext_scan_param_sync ( hdev , type , interval ,
window , own_addr_type ,
filter_policy ) ;
memset ( & cp , 0 , sizeof ( cp ) ) ;
cp . type = type ;
cp . interval = cpu_to_le16 ( interval ) ;
cp . window = cpu_to_le16 ( window ) ;
cp . own_address_type = own_addr_type ;
cp . filter_policy = filter_policy ;
return __hci_cmd_sync_status ( hdev , HCI_OP_LE_SET_SCAN_PARAM ,
sizeof ( cp ) , & cp , HCI_CMD_TIMEOUT ) ;
}
static int hci_start_scan_sync ( struct hci_dev * hdev , u8 type , u16 interval ,
Bluetooth: hci_sync: Convert MGMT_OP_START_DISCOVERY
This make use of hci_cmd_sync_queue for MGMT_OP_START_DISCOVERY,
MGMT_OP_START_SERVICE_DISCOVERY and MGMT_OP_STOP_DISCOVERY to use
hci_cmd_sync_queue so they no longer depend on hdev->discov_update work
to send any commands.
Tested with:
tools/mgmt-tester -s "Start Discovery"
Test Summary
------------
Start Discovery - Not powered 1 Passed
Start Discovery - Invalid parameters 1 Passed
Start Discovery - Not supported 1 Passed
Start Discovery - Success 1 Passed
Start Discovery - Success 2 Passed
Start Discovery - Power Off 1 Passed
Start Discovery BREDR LE - (Ext Scan Enable) Passed
Start Discovery LE - (Ext Scan Enable) Passed
Start Discovery LE - (Ext Scan Param) Passed
Start Discovery - (2m, Scan Param) Passed
Start Discovery - (coded, Scan Param) Passed
Start Discovery - (1m, 2m, coded, Scan Param) Passed
LL Privacy - Start Discovery 1 (Disable RL) Passed
LL Privacy - Start Discovery 2 (Disable RL) Passed
Total: 14, Passed: 14 (100.0%), Failed: 0, Not Run: 0
tools/mgmt-tester -s "Start Service"
Test Summary
------------
Start Service Discovery - Not powered 1 Passed
Start Service Discovery - Invalid parameters 1 Passed
Start Service Discovery - Not supported 1 Passed
Start Service Discovery - Success 1 Passed
Start Service Discovery - Success 2 Passed
Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0
tools/mgmt-tester -s "Stop Discovery"
Test Summary
------------
Stop Discovery - Success 1 Passed
Stop Discovery - BR/EDR (Inquiry) Success 1 Passed
Stop Discovery - Rejected 1 Passed
Stop Discovery - Invalid parameters 1 Passed
Stop Discovery - (Ext Scan Disable) Passed
Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-28 02:58:45 +03:00
u16 window , u8 own_addr_type , u8 filter_policy ,
u8 filter_dup )
2021-10-28 02:58:41 +03:00
{
int err ;
if ( hdev - > scanning_paused ) {
bt_dev_dbg ( hdev , " Scanning is paused for suspend " ) ;
return 0 ;
}
err = hci_le_set_scan_param_sync ( hdev , type , interval , window ,
own_addr_type , filter_policy ) ;
if ( err )
return err ;
Bluetooth: hci_sync: Convert MGMT_OP_START_DISCOVERY
This make use of hci_cmd_sync_queue for MGMT_OP_START_DISCOVERY,
MGMT_OP_START_SERVICE_DISCOVERY and MGMT_OP_STOP_DISCOVERY to use
hci_cmd_sync_queue so they no longer depend on hdev->discov_update work
to send any commands.
Tested with:
tools/mgmt-tester -s "Start Discovery"
Test Summary
------------
Start Discovery - Not powered 1 Passed
Start Discovery - Invalid parameters 1 Passed
Start Discovery - Not supported 1 Passed
Start Discovery - Success 1 Passed
Start Discovery - Success 2 Passed
Start Discovery - Power Off 1 Passed
Start Discovery BREDR LE - (Ext Scan Enable) Passed
Start Discovery LE - (Ext Scan Enable) Passed
Start Discovery LE - (Ext Scan Param) Passed
Start Discovery - (2m, Scan Param) Passed
Start Discovery - (coded, Scan Param) Passed
Start Discovery - (1m, 2m, coded, Scan Param) Passed
LL Privacy - Start Discovery 1 (Disable RL) Passed
LL Privacy - Start Discovery 2 (Disable RL) Passed
Total: 14, Passed: 14 (100.0%), Failed: 0, Not Run: 0
tools/mgmt-tester -s "Start Service"
Test Summary
------------
Start Service Discovery - Not powered 1 Passed
Start Service Discovery - Invalid parameters 1 Passed
Start Service Discovery - Not supported 1 Passed
Start Service Discovery - Success 1 Passed
Start Service Discovery - Success 2 Passed
Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0
tools/mgmt-tester -s "Stop Discovery"
Test Summary
------------
Stop Discovery - Success 1 Passed
Stop Discovery - BR/EDR (Inquiry) Success 1 Passed
Stop Discovery - Rejected 1 Passed
Stop Discovery - Invalid parameters 1 Passed
Stop Discovery - (Ext Scan Disable) Passed
Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-28 02:58:45 +03:00
return hci_le_set_scan_enable_sync ( hdev , LE_SCAN_ENABLE , filter_dup ) ;
2021-10-28 02:58:41 +03:00
}
int hci_passive_scan_sync ( struct hci_dev * hdev )
{
u8 own_addr_type ;
u8 filter_policy ;
u16 window , interval ;
2021-10-28 02:58:42 +03:00
int err ;
2021-10-28 02:58:41 +03:00
if ( hdev - > scanning_paused ) {
bt_dev_dbg ( hdev , " Scanning is paused for suspend " ) ;
return 0 ;
}
2021-10-28 02:58:42 +03:00
err = hci_scan_disable_sync ( hdev ) ;
if ( err ) {
bt_dev_err ( hdev , " disable scanning failed: %d " , err ) ;
return err ;
}
2021-10-28 02:58:41 +03:00
/* Set require_privacy to false since no SCAN_REQ are send
* during passive scanning . Not using an non - resolvable address
* here is important so that peer devices using direct
* advertising with our address will be correctly reported
* by the controller .
*/
if ( hci_update_random_address_sync ( hdev , false , scan_use_rpa ( hdev ) ,
& own_addr_type ) )
return 0 ;
if ( hdev - > enable_advmon_interleave_scan & &
hci_update_interleaved_scan_sync ( hdev ) )
return 0 ;
bt_dev_dbg ( hdev , " interleave state %d " , hdev - > interleave_scan_state ) ;
2021-10-28 02:58:42 +03:00
2021-10-28 02:58:41 +03:00
/* Adding or removing entries from the accept list must
* happen before enabling scanning . The controller does
* not allow accept list modification while scanning .
*/
filter_policy = hci_update_accept_list_sync ( hdev ) ;
/* When the controller is using random resolvable addresses and
* with that having LE privacy enabled , then controllers with
* Extended Scanner Filter Policies support can now enable support
* for handling directed advertising .
*
* So instead of using filter polices 0x00 ( no acceptlist )
* and 0x01 ( acceptlist enabled ) use the new filter policies
* 0x02 ( no acceptlist ) and 0x03 ( acceptlist enabled ) .
*/
if ( hci_dev_test_flag ( hdev , HCI_PRIVACY ) & &
( hdev - > le_features [ 0 ] & HCI_LE_EXT_SCAN_POLICY ) )
filter_policy | = 0x02 ;
if ( hdev - > suspended ) {
window = hdev - > le_scan_window_suspend ;
interval = hdev - > le_scan_int_suspend ;
set_bit ( SUSPEND_SCAN_ENABLE , hdev - > suspend_tasks ) ;
} else if ( hci_is_le_conn_scanning ( hdev ) ) {
window = hdev - > le_scan_window_connect ;
interval = hdev - > le_scan_int_connect ;
} else if ( hci_is_adv_monitoring ( hdev ) ) {
window = hdev - > le_scan_window_adv_monitor ;
interval = hdev - > le_scan_int_adv_monitor ;
} else {
window = hdev - > le_scan_window ;
interval = hdev - > le_scan_interval ;
}
bt_dev_dbg ( hdev , " LE passive scan with acceptlist = %d " , filter_policy ) ;
return hci_start_scan_sync ( hdev , LE_SCAN_PASSIVE , interval , window ,
Bluetooth: hci_sync: Convert MGMT_OP_START_DISCOVERY
This make use of hci_cmd_sync_queue for MGMT_OP_START_DISCOVERY,
MGMT_OP_START_SERVICE_DISCOVERY and MGMT_OP_STOP_DISCOVERY to use
hci_cmd_sync_queue so they no longer depend on hdev->discov_update work
to send any commands.
Tested with:
tools/mgmt-tester -s "Start Discovery"
Test Summary
------------
Start Discovery - Not powered 1 Passed
Start Discovery - Invalid parameters 1 Passed
Start Discovery - Not supported 1 Passed
Start Discovery - Success 1 Passed
Start Discovery - Success 2 Passed
Start Discovery - Power Off 1 Passed
Start Discovery BREDR LE - (Ext Scan Enable) Passed
Start Discovery LE - (Ext Scan Enable) Passed
Start Discovery LE - (Ext Scan Param) Passed
Start Discovery - (2m, Scan Param) Passed
Start Discovery - (coded, Scan Param) Passed
Start Discovery - (1m, 2m, coded, Scan Param) Passed
LL Privacy - Start Discovery 1 (Disable RL) Passed
LL Privacy - Start Discovery 2 (Disable RL) Passed
Total: 14, Passed: 14 (100.0%), Failed: 0, Not Run: 0
tools/mgmt-tester -s "Start Service"
Test Summary
------------
Start Service Discovery - Not powered 1 Passed
Start Service Discovery - Invalid parameters 1 Passed
Start Service Discovery - Not supported 1 Passed
Start Service Discovery - Success 1 Passed
Start Service Discovery - Success 2 Passed
Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0
tools/mgmt-tester -s "Stop Discovery"
Test Summary
------------
Stop Discovery - Success 1 Passed
Stop Discovery - BR/EDR (Inquiry) Success 1 Passed
Stop Discovery - Rejected 1 Passed
Stop Discovery - Invalid parameters 1 Passed
Stop Discovery - (Ext Scan Disable) Passed
Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-28 02:58:45 +03:00
own_addr_type , filter_policy ,
LE_SCAN_FILTER_DUP_ENABLE ) ;
2021-10-28 02:58:41 +03:00
}
/* This function controls the passive scanning based on hdev->pend_le_conns
* list . If there are pending LE connection we start the background scanning ,
2021-10-28 02:58:42 +03:00
* otherwise we stop it in the following sequence :
*
* If there are devices to scan :
*
* Disable Scanning - > Update Accept List - >
* use_ll_privacy ( ( Disable Advertising ) - > Disable Resolving List - >
* Update Resolving List - > Enable Resolving List - > ( Enable Advertising ) ) - >
* Enable Scanning
*
* Otherwise :
*
* Disable Scanning
2021-10-28 02:58:41 +03:00
*/
int hci_update_passive_scan_sync ( struct hci_dev * hdev )
{
int err ;
if ( ! test_bit ( HCI_UP , & hdev - > flags ) | |
test_bit ( HCI_INIT , & hdev - > flags ) | |
hci_dev_test_flag ( hdev , HCI_SETUP ) | |
hci_dev_test_flag ( hdev , HCI_CONFIG ) | |
hci_dev_test_flag ( hdev , HCI_AUTO_OFF ) | |
hci_dev_test_flag ( hdev , HCI_UNREGISTER ) )
return 0 ;
/* No point in doing scanning if LE support hasn't been enabled */
if ( ! hci_dev_test_flag ( hdev , HCI_LE_ENABLED ) )
return 0 ;
/* If discovery is active don't interfere with it */
if ( hdev - > discovery . state ! = DISCOVERY_STOPPED )
return 0 ;
/* Reset RSSI and UUID filters when starting background scanning
* since these filters are meant for service discovery only .
*
* The Start Discovery and Start Service Discovery operations
* ensure to set proper values for RSSI threshold and UUID
* filter list . So it is safe to just reset them here .
*/
hci_discovery_filter_clear ( hdev ) ;
bt_dev_dbg ( hdev , " ADV monitoring is %s " ,
hci_is_adv_monitoring ( hdev ) ? " on " : " off " ) ;
if ( list_empty ( & hdev - > pend_le_conns ) & &
list_empty ( & hdev - > pend_le_reports ) & &
! hci_is_adv_monitoring ( hdev ) ) {
/* If there is no pending LE connections or devices
* to be scanned for or no ADV monitors , we should stop the
* background scanning .
*/
bt_dev_dbg ( hdev , " stopping background scanning " ) ;
2021-10-28 02:58:42 +03:00
err = hci_scan_disable_sync ( hdev ) ;
2021-10-28 02:58:41 +03:00
if ( err )
bt_dev_err ( hdev , " stop background scanning failed: %d " ,
err ) ;
} else {
/* If there is at least one pending LE connection, we should
* keep the background scan running .
*/
/* If controller is connecting, we should not start scanning
* since some controllers are not able to scan and connect at
* the same time .
*/
if ( hci_lookup_le_connect ( hdev ) )
return 0 ;
bt_dev_dbg ( hdev , " start background scanning " ) ;
err = hci_passive_scan_sync ( hdev ) ;
if ( err )
bt_dev_err ( hdev , " start background scanning failed: %d " ,
err ) ;
}
return err ;
}
2021-10-28 02:58:42 +03:00
static int update_passive_scan_sync ( struct hci_dev * hdev , void * data )
{
return hci_update_passive_scan_sync ( hdev ) ;
}
int hci_update_passive_scan ( struct hci_dev * hdev )
{
2021-10-28 02:58:43 +03:00
/* Only queue if it would have any effect */
if ( ! test_bit ( HCI_UP , & hdev - > flags ) | |
test_bit ( HCI_INIT , & hdev - > flags ) | |
hci_dev_test_flag ( hdev , HCI_SETUP ) | |
hci_dev_test_flag ( hdev , HCI_CONFIG ) | |
hci_dev_test_flag ( hdev , HCI_AUTO_OFF ) | |
hci_dev_test_flag ( hdev , HCI_UNREGISTER ) )
return 0 ;
2021-10-28 02:58:42 +03:00
return hci_cmd_sync_queue ( hdev , update_passive_scan_sync , NULL , NULL ) ;
}
2021-10-28 02:58:44 +03:00
static int hci_write_sc_support_sync ( struct hci_dev * hdev , u8 val )
{
if ( ! bredr_sc_enabled ( hdev ) | | lmp_host_sc_capable ( hdev ) )
return 0 ;
return __hci_cmd_sync_status ( hdev , HCI_OP_WRITE_SC_SUPPORT ,
sizeof ( val ) , & val , HCI_CMD_TIMEOUT ) ;
}
static int hci_write_ssp_mode_sync ( struct hci_dev * hdev , u8 mode )
{
int err ;
if ( ! hci_dev_test_flag ( hdev , HCI_SSP_ENABLED ) | |
lmp_host_ssp_capable ( hdev ) )
return 0 ;
err = __hci_cmd_sync_status ( hdev , HCI_OP_WRITE_SSP_MODE ,
sizeof ( mode ) , & mode , HCI_CMD_TIMEOUT ) ;
if ( err )
return err ;
return hci_write_sc_support_sync ( hdev , 0x01 ) ;
}
static int hci_write_le_host_supported_sync ( struct hci_dev * hdev , u8 le ,
u8 simul )
{
struct hci_cp_write_le_host_supported cp ;
if ( ! hci_dev_test_flag ( hdev , HCI_LE_ENABLED ) | |
! lmp_bredr_capable ( hdev ) )
return 0 ;
/* Check first if we already have the right host state
* ( host features set )
*/
if ( le = = lmp_host_le_capable ( hdev ) & &
simul = = lmp_host_le_br_capable ( hdev ) )
return 0 ;
memset ( & cp , 0 , sizeof ( cp ) ) ;
cp . le = le ;
cp . simul = simul ;
return __hci_cmd_sync_status ( hdev , HCI_OP_WRITE_LE_HOST_SUPPORTED ,
sizeof ( cp ) , & cp , HCI_CMD_TIMEOUT ) ;
}
static int hci_powered_update_adv_sync ( struct hci_dev * hdev )
{
struct adv_info * adv , * tmp ;
int err ;
if ( ! hci_dev_test_flag ( hdev , HCI_LE_ENABLED ) )
return 0 ;
/* If RPA Resolution has not been enable yet it means the
* resolving list is empty and we should attempt to program the
* local IRK in order to support using own_addr_type
* ADDR_LE_DEV_RANDOM_RESOLVED ( 0x03 ) .
*/
if ( ! hci_dev_test_flag ( hdev , HCI_LL_RPA_RESOLUTION ) ) {
hci_le_add_resolve_list_sync ( hdev , NULL ) ;
hci_le_set_addr_resolution_enable_sync ( hdev , 0x01 ) ;
}
/* Make sure the controller has a good default for
* advertising data . This also applies to the case
* where BR / EDR was toggled during the AUTO_OFF phase .
*/
if ( hci_dev_test_flag ( hdev , HCI_ADVERTISING ) | |
list_empty ( & hdev - > adv_instances ) ) {
if ( ext_adv_capable ( hdev ) ) {
err = hci_setup_ext_adv_instance_sync ( hdev , 0x00 ) ;
if ( ! err )
hci_update_scan_rsp_data_sync ( hdev , 0x00 ) ;
} else {
err = hci_update_adv_data_sync ( hdev , 0x00 ) ;
if ( ! err )
hci_update_scan_rsp_data_sync ( hdev , 0x00 ) ;
}
if ( hci_dev_test_flag ( hdev , HCI_ADVERTISING ) )
hci_enable_advertising_sync ( hdev ) ;
}
/* Call for each tracked instance to be scheduled */
list_for_each_entry_safe ( adv , tmp , & hdev - > adv_instances , list )
hci_schedule_adv_instance_sync ( hdev , adv - > instance , true ) ;
return 0 ;
}
static int hci_write_auth_enable_sync ( struct hci_dev * hdev )
{
u8 link_sec ;
link_sec = hci_dev_test_flag ( hdev , HCI_LINK_SECURITY ) ;
if ( link_sec = = test_bit ( HCI_AUTH , & hdev - > flags ) )
return 0 ;
return __hci_cmd_sync_status ( hdev , HCI_OP_WRITE_AUTH_ENABLE ,
sizeof ( link_sec ) , & link_sec ,
HCI_CMD_TIMEOUT ) ;
}
static int hci_write_fast_connectable_sync ( struct hci_dev * hdev , bool enable )
{
struct hci_cp_write_page_scan_activity cp ;
u8 type ;
int err = 0 ;
if ( ! hci_dev_test_flag ( hdev , HCI_BREDR_ENABLED ) )
return 0 ;
if ( hdev - > hci_ver < BLUETOOTH_VER_1_2 )
return 0 ;
memset ( & cp , 0 , sizeof ( cp ) ) ;
if ( enable ) {
type = PAGE_SCAN_TYPE_INTERLACED ;
/* 160 msec page scan interval */
cp . interval = cpu_to_le16 ( 0x0100 ) ;
} else {
type = hdev - > def_page_scan_type ;
cp . interval = cpu_to_le16 ( hdev - > def_page_scan_int ) ;
}
cp . window = cpu_to_le16 ( hdev - > def_page_scan_window ) ;
if ( __cpu_to_le16 ( hdev - > page_scan_interval ) ! = cp . interval | |
__cpu_to_le16 ( hdev - > page_scan_window ) ! = cp . window ) {
err = __hci_cmd_sync_status ( hdev ,
HCI_OP_WRITE_PAGE_SCAN_ACTIVITY ,
sizeof ( cp ) , & cp , HCI_CMD_TIMEOUT ) ;
if ( err )
return err ;
}
if ( hdev - > page_scan_type ! = type )
err = __hci_cmd_sync_status ( hdev ,
HCI_OP_WRITE_PAGE_SCAN_TYPE ,
sizeof ( type ) , & type ,
HCI_CMD_TIMEOUT ) ;
return err ;
}
static bool disconnected_accept_list_entries ( struct hci_dev * hdev )
{
struct bdaddr_list * b ;
list_for_each_entry ( b , & hdev - > accept_list , list ) {
struct hci_conn * conn ;
conn = hci_conn_hash_lookup_ba ( hdev , ACL_LINK , & b - > bdaddr ) ;
if ( ! conn )
return true ;
if ( conn - > state ! = BT_CONNECTED & & conn - > state ! = BT_CONFIG )
return true ;
}
return false ;
}
static int hci_write_scan_enable_sync ( struct hci_dev * hdev , u8 val )
{
return __hci_cmd_sync_status ( hdev , HCI_OP_WRITE_SCAN_ENABLE ,
sizeof ( val ) , & val ,
HCI_CMD_TIMEOUT ) ;
}
static int hci_update_scan_sync ( struct hci_dev * hdev )
{
u8 scan ;
if ( ! hci_dev_test_flag ( hdev , HCI_BREDR_ENABLED ) )
return 0 ;
if ( ! hdev_is_powered ( hdev ) )
return 0 ;
if ( mgmt_powering_down ( hdev ) )
return 0 ;
if ( hdev - > scanning_paused )
return 0 ;
if ( hci_dev_test_flag ( hdev , HCI_CONNECTABLE ) | |
disconnected_accept_list_entries ( hdev ) )
scan = SCAN_PAGE ;
else
scan = SCAN_DISABLED ;
if ( hci_dev_test_flag ( hdev , HCI_DISCOVERABLE ) )
scan | = SCAN_INQUIRY ;
if ( test_bit ( HCI_PSCAN , & hdev - > flags ) = = ! ! ( scan & SCAN_PAGE ) & &
test_bit ( HCI_ISCAN , & hdev - > flags ) = = ! ! ( scan & SCAN_INQUIRY ) )
return 0 ;
return hci_write_scan_enable_sync ( hdev , scan ) ;
}
static int hci_update_name_sync ( struct hci_dev * hdev )
{
struct hci_cp_write_local_name cp ;
memset ( & cp , 0 , sizeof ( cp ) ) ;
memcpy ( cp . name , hdev - > dev_name , sizeof ( cp . name ) ) ;
return __hci_cmd_sync_status ( hdev , HCI_OP_WRITE_LOCAL_NAME ,
sizeof ( cp ) , & cp ,
HCI_CMD_TIMEOUT ) ;
}
/* This function perform powered update HCI command sequence after the HCI init
* sequence which end up resetting all states , the sequence is as follows :
*
* HCI_SSP_ENABLED ( Enable SSP )
* HCI_LE_ENABLED ( Enable LE )
* HCI_LE_ENABLED ( use_ll_privacy ( Add local IRK to Resolving List ) - >
* Update adv data )
* Enable Authentication
* lmp_bredr_capable ( Set Fast Connectable - > Set Scan Type - > Set Class - >
* Set Name - > Set EIR )
*/
int hci_powered_update_sync ( struct hci_dev * hdev )
{
int err ;
/* Register the available SMP channels (BR/EDR and LE) only when
* successfully powering on the controller . This late
* registration is required so that LE SMP can clearly decide if
* the public address or static address is used .
*/
smp_register ( hdev ) ;
err = hci_write_ssp_mode_sync ( hdev , 0x01 ) ;
if ( err )
return err ;
err = hci_write_le_host_supported_sync ( hdev , 0x01 , 0x00 ) ;
if ( err )
return err ;
err = hci_powered_update_adv_sync ( hdev ) ;
if ( err )
return err ;
err = hci_write_auth_enable_sync ( hdev ) ;
if ( err )
return err ;
if ( lmp_bredr_capable ( hdev ) ) {
if ( hci_dev_test_flag ( hdev , HCI_FAST_CONNECTABLE ) )
hci_write_fast_connectable_sync ( hdev , true ) ;
else
hci_write_fast_connectable_sync ( hdev , false ) ;
hci_update_scan_sync ( hdev ) ;
hci_update_class_sync ( hdev ) ;
hci_update_name_sync ( hdev ) ;
hci_update_eir_sync ( hdev ) ;
}
return 0 ;
}
/* This function perform power on HCI command sequence as follows:
*
* If controller is already up ( HCI_UP ) performs hci_powered_update_sync
* sequence otherwise run hci_dev_open_sync which will follow with
* hci_powered_update_sync after the init sequence is completed .
*/
static int hci_power_on_sync ( struct hci_dev * hdev )
{
int err ;
if ( test_bit ( HCI_UP , & hdev - > flags ) & &
hci_dev_test_flag ( hdev , HCI_MGMT ) & &
hci_dev_test_and_clear_flag ( hdev , HCI_AUTO_OFF ) ) {
cancel_delayed_work ( & hdev - > power_off ) ;
return hci_powered_update_sync ( hdev ) ;
}
err = hci_dev_open_sync ( hdev ) ;
if ( err < 0 )
return err ;
/* During the HCI setup phase, a few error conditions are
* ignored and they need to be checked now . If they are still
* valid , it is important to return the device back off .
*/
if ( hci_dev_test_flag ( hdev , HCI_RFKILLED ) | |
hci_dev_test_flag ( hdev , HCI_UNCONFIGURED ) | |
( hdev - > dev_type = = HCI_PRIMARY & &
! bacmp ( & hdev - > bdaddr , BDADDR_ANY ) & &
! bacmp ( & hdev - > static_addr , BDADDR_ANY ) ) ) {
hci_dev_clear_flag ( hdev , HCI_AUTO_OFF ) ;
hci_dev_close_sync ( hdev ) ;
} else if ( hci_dev_test_flag ( hdev , HCI_AUTO_OFF ) ) {
queue_delayed_work ( hdev - > req_workqueue , & hdev - > power_off ,
HCI_AUTO_OFF_TIMEOUT ) ;
}
if ( hci_dev_test_and_clear_flag ( hdev , HCI_SETUP ) ) {
/* For unconfigured devices, set the HCI_RAW flag
* so that userspace can easily identify them .
*/
if ( hci_dev_test_flag ( hdev , HCI_UNCONFIGURED ) )
set_bit ( HCI_RAW , & hdev - > flags ) ;
/* For fully configured devices, this will send
* the Index Added event . For unconfigured devices ,
* it will send Unconfigued Index Added event .
*
* Devices with HCI_QUIRK_RAW_DEVICE are ignored
* and no event will be send .
*/
mgmt_index_added ( hdev ) ;
} else if ( hci_dev_test_and_clear_flag ( hdev , HCI_CONFIG ) ) {
/* When the controller is now configured, then it
* is important to clear the HCI_RAW flag .
*/
if ( ! hci_dev_test_flag ( hdev , HCI_UNCONFIGURED ) )
clear_bit ( HCI_RAW , & hdev - > flags ) ;
/* Powering on the controller with HCI_CONFIG set only
* happens with the transition from unconfigured to
* configured . This will send the Index Added event .
*/
mgmt_index_added ( hdev ) ;
}
return 0 ;
}
static int hci_remote_name_cancel_sync ( struct hci_dev * hdev , bdaddr_t * addr )
{
struct hci_cp_remote_name_req_cancel cp ;
memset ( & cp , 0 , sizeof ( cp ) ) ;
bacpy ( & cp . bdaddr , addr ) ;
return __hci_cmd_sync_status ( hdev , HCI_OP_REMOTE_NAME_REQ_CANCEL ,
sizeof ( cp ) , & cp , HCI_CMD_TIMEOUT ) ;
}
Bluetooth: hci_sync: Convert MGMT_OP_START_DISCOVERY
This make use of hci_cmd_sync_queue for MGMT_OP_START_DISCOVERY,
MGMT_OP_START_SERVICE_DISCOVERY and MGMT_OP_STOP_DISCOVERY to use
hci_cmd_sync_queue so they no longer depend on hdev->discov_update work
to send any commands.
Tested with:
tools/mgmt-tester -s "Start Discovery"
Test Summary
------------
Start Discovery - Not powered 1 Passed
Start Discovery - Invalid parameters 1 Passed
Start Discovery - Not supported 1 Passed
Start Discovery - Success 1 Passed
Start Discovery - Success 2 Passed
Start Discovery - Power Off 1 Passed
Start Discovery BREDR LE - (Ext Scan Enable) Passed
Start Discovery LE - (Ext Scan Enable) Passed
Start Discovery LE - (Ext Scan Param) Passed
Start Discovery - (2m, Scan Param) Passed
Start Discovery - (coded, Scan Param) Passed
Start Discovery - (1m, 2m, coded, Scan Param) Passed
LL Privacy - Start Discovery 1 (Disable RL) Passed
LL Privacy - Start Discovery 2 (Disable RL) Passed
Total: 14, Passed: 14 (100.0%), Failed: 0, Not Run: 0
tools/mgmt-tester -s "Start Service"
Test Summary
------------
Start Service Discovery - Not powered 1 Passed
Start Service Discovery - Invalid parameters 1 Passed
Start Service Discovery - Not supported 1 Passed
Start Service Discovery - Success 1 Passed
Start Service Discovery - Success 2 Passed
Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0
tools/mgmt-tester -s "Stop Discovery"
Test Summary
------------
Stop Discovery - Success 1 Passed
Stop Discovery - BR/EDR (Inquiry) Success 1 Passed
Stop Discovery - Rejected 1 Passed
Stop Discovery - Invalid parameters 1 Passed
Stop Discovery - (Ext Scan Disable) Passed
Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-28 02:58:45 +03:00
int hci_stop_discovery_sync ( struct hci_dev * hdev )
2021-10-28 02:58:44 +03:00
{
struct discovery_state * d = & hdev - > discovery ;
struct inquiry_entry * e ;
int err ;
bt_dev_dbg ( hdev , " state %u " , hdev - > discovery . state ) ;
if ( d - > state = = DISCOVERY_FINDING | | d - > state = = DISCOVERY_STOPPING ) {
if ( test_bit ( HCI_INQUIRY , & hdev - > flags ) ) {
err = __hci_cmd_sync_status ( hdev , HCI_OP_INQUIRY_CANCEL ,
0 , NULL , HCI_CMD_TIMEOUT ) ;
if ( err )
return err ;
}
if ( hci_dev_test_flag ( hdev , HCI_LE_SCAN ) ) {
cancel_delayed_work ( & hdev - > le_scan_disable ) ;
cancel_delayed_work ( & hdev - > le_scan_restart ) ;
err = hci_scan_disable_sync ( hdev ) ;
if ( err )
return err ;
}
} else {
err = hci_scan_disable_sync ( hdev ) ;
if ( err )
return err ;
}
Bluetooth: hci_sync: Convert MGMT_OP_START_DISCOVERY
This make use of hci_cmd_sync_queue for MGMT_OP_START_DISCOVERY,
MGMT_OP_START_SERVICE_DISCOVERY and MGMT_OP_STOP_DISCOVERY to use
hci_cmd_sync_queue so they no longer depend on hdev->discov_update work
to send any commands.
Tested with:
tools/mgmt-tester -s "Start Discovery"
Test Summary
------------
Start Discovery - Not powered 1 Passed
Start Discovery - Invalid parameters 1 Passed
Start Discovery - Not supported 1 Passed
Start Discovery - Success 1 Passed
Start Discovery - Success 2 Passed
Start Discovery - Power Off 1 Passed
Start Discovery BREDR LE - (Ext Scan Enable) Passed
Start Discovery LE - (Ext Scan Enable) Passed
Start Discovery LE - (Ext Scan Param) Passed
Start Discovery - (2m, Scan Param) Passed
Start Discovery - (coded, Scan Param) Passed
Start Discovery - (1m, 2m, coded, Scan Param) Passed
LL Privacy - Start Discovery 1 (Disable RL) Passed
LL Privacy - Start Discovery 2 (Disable RL) Passed
Total: 14, Passed: 14 (100.0%), Failed: 0, Not Run: 0
tools/mgmt-tester -s "Start Service"
Test Summary
------------
Start Service Discovery - Not powered 1 Passed
Start Service Discovery - Invalid parameters 1 Passed
Start Service Discovery - Not supported 1 Passed
Start Service Discovery - Success 1 Passed
Start Service Discovery - Success 2 Passed
Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0
tools/mgmt-tester -s "Stop Discovery"
Test Summary
------------
Stop Discovery - Success 1 Passed
Stop Discovery - BR/EDR (Inquiry) Success 1 Passed
Stop Discovery - Rejected 1 Passed
Stop Discovery - Invalid parameters 1 Passed
Stop Discovery - (Ext Scan Disable) Passed
Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-28 02:58:45 +03:00
/* Resume advertising if it was paused */
if ( use_ll_privacy ( hdev ) )
hci_resume_advertising_sync ( hdev ) ;
2021-10-28 02:58:44 +03:00
/* No further actions needed for LE-only discovery */
if ( d - > type = = DISCOV_TYPE_LE )
return 0 ;
if ( d - > state = = DISCOVERY_RESOLVING | | d - > state = = DISCOVERY_STOPPING ) {
e = hci_inquiry_cache_lookup_resolve ( hdev , BDADDR_ANY ,
NAME_PENDING ) ;
if ( ! e )
return 0 ;
return hci_remote_name_cancel_sync ( hdev , & e - > data . bdaddr ) ;
}
return 0 ;
}
static int hci_disconnect_phy_link_sync ( struct hci_dev * hdev , u16 handle ,
u8 reason )
{
struct hci_cp_disconn_phy_link cp ;
memset ( & cp , 0 , sizeof ( cp ) ) ;
cp . phy_handle = HCI_PHY_HANDLE ( handle ) ;
cp . reason = reason ;
return __hci_cmd_sync_status ( hdev , HCI_OP_DISCONN_PHY_LINK ,
sizeof ( cp ) , & cp , HCI_CMD_TIMEOUT ) ;
}
static int hci_disconnect_sync ( struct hci_dev * hdev , struct hci_conn * conn ,
u8 reason )
{
struct hci_cp_disconnect cp ;
if ( conn - > type = = AMP_LINK )
return hci_disconnect_phy_link_sync ( hdev , conn - > handle , reason ) ;
memset ( & cp , 0 , sizeof ( cp ) ) ;
cp . handle = cpu_to_le16 ( conn - > handle ) ;
cp . reason = reason ;
return __hci_cmd_sync_status ( hdev , HCI_OP_DISCONNECT ,
sizeof ( cp ) , & cp , HCI_CMD_TIMEOUT ) ;
}
static int hci_le_connect_cancel_sync ( struct hci_dev * hdev ,
struct hci_conn * conn )
{
if ( test_bit ( HCI_CONN_SCANNING , & conn - > flags ) )
return 0 ;
return __hci_cmd_sync_status ( hdev , HCI_OP_LE_CREATE_CONN_CANCEL ,
6 , & conn - > dst , HCI_CMD_TIMEOUT ) ;
}
static int hci_connect_cancel_sync ( struct hci_dev * hdev , struct hci_conn * conn )
{
if ( conn - > type = = LE_LINK )
return hci_le_connect_cancel_sync ( hdev , conn ) ;
if ( hdev - > hci_ver < BLUETOOTH_VER_1_2 )
return 0 ;
return __hci_cmd_sync_status ( hdev , HCI_OP_CREATE_CONN_CANCEL ,
6 , & conn - > dst , HCI_CMD_TIMEOUT ) ;
}
static int hci_reject_sco_sync ( struct hci_dev * hdev , struct hci_conn * conn ,
u8 reason )
{
struct hci_cp_reject_sync_conn_req cp ;
memset ( & cp , 0 , sizeof ( cp ) ) ;
bacpy ( & cp . bdaddr , & conn - > dst ) ;
cp . reason = reason ;
/* SCO rejection has its own limited set of
* allowed error values ( 0x0D - 0x0F ) .
*/
if ( reason < 0x0d | | reason > 0x0f )
cp . reason = HCI_ERROR_REJ_LIMITED_RESOURCES ;
return __hci_cmd_sync_status ( hdev , HCI_OP_REJECT_SYNC_CONN_REQ ,
sizeof ( cp ) , & cp , HCI_CMD_TIMEOUT ) ;
}
static int hci_reject_conn_sync ( struct hci_dev * hdev , struct hci_conn * conn ,
u8 reason )
{
struct hci_cp_reject_conn_req cp ;
if ( conn - > type = = SCO_LINK | | conn - > type = = ESCO_LINK )
return hci_reject_sco_sync ( hdev , conn , reason ) ;
memset ( & cp , 0 , sizeof ( cp ) ) ;
bacpy ( & cp . bdaddr , & conn - > dst ) ;
cp . reason = reason ;
return __hci_cmd_sync_status ( hdev , HCI_OP_REJECT_CONN_REQ ,
sizeof ( cp ) , & cp , HCI_CMD_TIMEOUT ) ;
}
static int hci_abort_conn_sync ( struct hci_dev * hdev , struct hci_conn * conn ,
u8 reason )
{
switch ( conn - > state ) {
case BT_CONNECTED :
case BT_CONFIG :
return hci_disconnect_sync ( hdev , conn , reason ) ;
case BT_CONNECT :
return hci_connect_cancel_sync ( hdev , conn ) ;
case BT_CONNECT2 :
return hci_reject_conn_sync ( hdev , conn , reason ) ;
default :
conn - > state = BT_CLOSED ;
break ;
}
return 0 ;
}
/* This function perform power off HCI command sequence as follows:
*
* Clear Advertising
* Stop Discovery
* Disconnect all connections
* hci_dev_close_sync
*/
static int hci_power_off_sync ( struct hci_dev * hdev )
{
struct hci_conn * conn ;
int err ;
/* If controller is already down there is nothing to do */
if ( ! test_bit ( HCI_UP , & hdev - > flags ) )
return 0 ;
if ( test_bit ( HCI_ISCAN , & hdev - > flags ) | |
test_bit ( HCI_PSCAN , & hdev - > flags ) ) {
err = hci_write_scan_enable_sync ( hdev , 0x00 ) ;
if ( err )
return err ;
}
err = hci_clear_adv_sync ( hdev , NULL , false ) ;
if ( err )
return err ;
err = hci_stop_discovery_sync ( hdev ) ;
if ( err )
return err ;
list_for_each_entry ( conn , & hdev - > conn_hash . list , list ) {
/* 0x15 == Terminated due to Power Off */
hci_abort_conn_sync ( hdev , conn , 0x15 ) ;
}
return hci_dev_close_sync ( hdev ) ;
}
int hci_set_powered_sync ( struct hci_dev * hdev , u8 val )
{
if ( val )
return hci_power_on_sync ( hdev ) ;
return hci_power_off_sync ( hdev ) ;
}
Bluetooth: hci_sync: Convert MGMT_OP_START_DISCOVERY
This make use of hci_cmd_sync_queue for MGMT_OP_START_DISCOVERY,
MGMT_OP_START_SERVICE_DISCOVERY and MGMT_OP_STOP_DISCOVERY to use
hci_cmd_sync_queue so they no longer depend on hdev->discov_update work
to send any commands.
Tested with:
tools/mgmt-tester -s "Start Discovery"
Test Summary
------------
Start Discovery - Not powered 1 Passed
Start Discovery - Invalid parameters 1 Passed
Start Discovery - Not supported 1 Passed
Start Discovery - Success 1 Passed
Start Discovery - Success 2 Passed
Start Discovery - Power Off 1 Passed
Start Discovery BREDR LE - (Ext Scan Enable) Passed
Start Discovery LE - (Ext Scan Enable) Passed
Start Discovery LE - (Ext Scan Param) Passed
Start Discovery - (2m, Scan Param) Passed
Start Discovery - (coded, Scan Param) Passed
Start Discovery - (1m, 2m, coded, Scan Param) Passed
LL Privacy - Start Discovery 1 (Disable RL) Passed
LL Privacy - Start Discovery 2 (Disable RL) Passed
Total: 14, Passed: 14 (100.0%), Failed: 0, Not Run: 0
tools/mgmt-tester -s "Start Service"
Test Summary
------------
Start Service Discovery - Not powered 1 Passed
Start Service Discovery - Invalid parameters 1 Passed
Start Service Discovery - Not supported 1 Passed
Start Service Discovery - Success 1 Passed
Start Service Discovery - Success 2 Passed
Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0
tools/mgmt-tester -s "Stop Discovery"
Test Summary
------------
Stop Discovery - Success 1 Passed
Stop Discovery - BR/EDR (Inquiry) Success 1 Passed
Stop Discovery - Rejected 1 Passed
Stop Discovery - Invalid parameters 1 Passed
Stop Discovery - (Ext Scan Disable) Passed
Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-28 02:58:45 +03:00
static int hci_inquiry_sync ( struct hci_dev * hdev , u8 length )
{
const u8 giac [ 3 ] = { 0x33 , 0x8b , 0x9e } ;
const u8 liac [ 3 ] = { 0x00 , 0x8b , 0x9e } ;
struct hci_cp_inquiry cp ;
bt_dev_dbg ( hdev , " " ) ;
if ( hci_dev_test_flag ( hdev , HCI_INQUIRY ) )
return 0 ;
hci_dev_lock ( hdev ) ;
hci_inquiry_cache_flush ( hdev ) ;
hci_dev_unlock ( hdev ) ;
memset ( & cp , 0 , sizeof ( cp ) ) ;
if ( hdev - > discovery . limited )
memcpy ( & cp . lap , liac , sizeof ( cp . lap ) ) ;
else
memcpy ( & cp . lap , giac , sizeof ( cp . lap ) ) ;
cp . length = length ;
return __hci_cmd_sync_status ( hdev , HCI_OP_INQUIRY ,
sizeof ( cp ) , & cp , HCI_CMD_TIMEOUT ) ;
}
static int hci_active_scan_sync ( struct hci_dev * hdev , uint16_t interval )
{
u8 own_addr_type ;
/* Accept list is not used for discovery */
u8 filter_policy = 0x00 ;
/* Default is to enable duplicates filter */
u8 filter_dup = LE_SCAN_FILTER_DUP_ENABLE ;
int err ;
bt_dev_dbg ( hdev , " " ) ;
/* If controller is scanning, it means the passive scanning is
* running . Thus , we should temporarily stop it in order to set the
* discovery scanning parameters .
*/
err = hci_scan_disable_sync ( hdev ) ;
if ( err ) {
bt_dev_err ( hdev , " Unable to disable scanning: %d " , err ) ;
return err ;
}
cancel_interleave_scan ( hdev ) ;
/* Pause advertising since active scanning disables address resolution
* which advertising depend on in order to generate its RPAs .
*/
if ( use_ll_privacy ( hdev ) ) {
err = hci_pause_advertising_sync ( hdev ) ;
if ( err ) {
bt_dev_err ( hdev , " pause advertising failed: %d " , err ) ;
goto failed ;
}
}
/* Disable address resolution while doing active scanning since the
* accept list shall not be used and all reports shall reach the host
* anyway .
*/
err = hci_le_set_addr_resolution_enable_sync ( hdev , 0x00 ) ;
if ( err ) {
bt_dev_err ( hdev , " Unable to disable Address Resolution: %d " ,
err ) ;
goto failed ;
}
/* All active scans will be done with either a resolvable private
* address ( when privacy feature has been enabled ) or non - resolvable
* private address .
*/
err = hci_update_random_address_sync ( hdev , true , scan_use_rpa ( hdev ) ,
& own_addr_type ) ;
if ( err < 0 )
own_addr_type = ADDR_LE_DEV_PUBLIC ;
if ( hci_is_adv_monitoring ( hdev ) ) {
/* Duplicate filter should be disabled when some advertisement
* monitor is activated , otherwise AdvMon can only receive one
* advertisement for one peer ( * ) during active scanning , and
* might report loss to these peers .
*
* Note that different controllers have different meanings of
* | duplicate | . Some of them consider packets with the same
* address as duplicate , and others consider packets with the
* same address and the same RSSI as duplicate . Although in the
* latter case we don ' t need to disable duplicate filter , but
* it is common to have active scanning for a short period of
* time , the power impact should be neglectable .
*/
filter_dup = LE_SCAN_FILTER_DUP_DISABLE ;
}
err = hci_start_scan_sync ( hdev , LE_SCAN_ACTIVE , interval ,
hdev - > le_scan_window_discovery ,
own_addr_type , filter_policy , filter_dup ) ;
if ( ! err )
return err ;
failed :
/* Resume advertising if it was paused */
if ( use_ll_privacy ( hdev ) )
hci_resume_advertising_sync ( hdev ) ;
/* Resume passive scanning */
hci_update_passive_scan_sync ( hdev ) ;
return err ;
}
static int hci_start_interleaved_discovery_sync ( struct hci_dev * hdev )
{
int err ;
bt_dev_dbg ( hdev , " " ) ;
err = hci_active_scan_sync ( hdev , hdev - > le_scan_int_discovery * 2 ) ;
if ( err )
return err ;
return hci_inquiry_sync ( hdev , DISCOV_BREDR_INQUIRY_LEN ) ;
}
int hci_start_discovery_sync ( struct hci_dev * hdev )
{
unsigned long timeout ;
int err ;
bt_dev_dbg ( hdev , " type %u " , hdev - > discovery . type ) ;
switch ( hdev - > discovery . type ) {
case DISCOV_TYPE_BREDR :
return hci_inquiry_sync ( hdev , DISCOV_BREDR_INQUIRY_LEN ) ;
case DISCOV_TYPE_INTERLEAVED :
/* When running simultaneous discovery, the LE scanning time
* should occupy the whole discovery time sine BR / EDR inquiry
* and LE scanning are scheduled by the controller .
*
* For interleaving discovery in comparison , BR / EDR inquiry
* and LE scanning are done sequentially with separate
* timeouts .
*/
if ( test_bit ( HCI_QUIRK_SIMULTANEOUS_DISCOVERY ,
& hdev - > quirks ) ) {
timeout = msecs_to_jiffies ( DISCOV_LE_TIMEOUT ) ;
/* During simultaneous discovery, we double LE scan
* interval . We must leave some time for the controller
* to do BR / EDR inquiry .
*/
err = hci_start_interleaved_discovery_sync ( hdev ) ;
break ;
}
timeout = msecs_to_jiffies ( hdev - > discov_interleaved_timeout ) ;
err = hci_active_scan_sync ( hdev , hdev - > le_scan_int_discovery ) ;
break ;
case DISCOV_TYPE_LE :
timeout = msecs_to_jiffies ( DISCOV_LE_TIMEOUT ) ;
err = hci_active_scan_sync ( hdev , hdev - > le_scan_int_discovery ) ;
break ;
default :
return - EINVAL ;
}
if ( err )
return err ;
bt_dev_dbg ( hdev , " timeout %u ms " , jiffies_to_msecs ( timeout ) ) ;
/* When service discovery is used and the controller has a
* strict duplicate filter , it is important to remember the
* start and duration of the scan . This is required for
* restarting scanning during the discovery phase .
*/
if ( test_bit ( HCI_QUIRK_STRICT_DUPLICATE_FILTER , & hdev - > quirks ) & &
hdev - > discovery . result_filtering ) {
hdev - > discovery . scan_start = jiffies ;
hdev - > discovery . scan_duration = timeout ;
}
queue_delayed_work ( hdev - > req_workqueue , & hdev - > le_scan_disable ,
timeout ) ;
return 0 ;
}