mirror of
https://github.com/torvalds/linux.git
synced 2026-05-30 01:53:29 +02:00
bluetooth-next pull request for net-next:
- btnxpuart: Fix recv_buf return value
- L2CAP: Fix responding with multiple rejects
- Fix atomicity violation in {min,max}_key_size_set
- ISO: Allow binding a PA sync socket
- ISO: Reassociate a socket with an active BIS
- ISO: Avoid creating child socket if PA sync is terminating
- Add device 13d3:3572 IMC Networks Bluetooth Radio
- Don't suspend when there are connections
- Remove le_restart_scan work
- Fix bogus check for re-auth not supported with non-ssp
- lib: Add documentation to exported functions
- Support HFP offload for QCA2066
-----BEGIN PGP SIGNATURE-----
iQJNBAABCAA3FiEE7E6oRXp8w05ovYr/9JCA4xAyCykFAmWF2P4ZHGx1aXoudm9u
LmRlbnR6QGludGVsLmNvbQAKCRD0kIDjEDILKZ3eEACgIk7eorrf+isIBZjq+qGL
0ESqGe2ZnRupnJs6fRFBY2L8jWkfZbURzUKXVpt0fVrQAb8qzrEzwD/ucApT38SY
LO1lzLhPLfUpwXS4jW5pFvA+tLDS6sb9fBd/tp1ikaNavU3FTfWFeGJmJH8nubHc
qZqOkBblm34yrdlEZwxiJxviVmbAsHHSu1AWXZ9yTO5Z5HRNUN0jxBYjOPVHkrdx
SdP8J+icTMQ7ywoFEOLAnDaJi+bKMPwyGlz6opx75L0LkdbqjFwdu+1X6ZtjLsP3
c51RJtdJgBJY8TX5MmwMEakHQSbcGBUPeEMhZqrrzY1A/2dsb85T4acXgU1iV6Ws
SkYFFeEWiBhV/WJn4a/mZzMASRzpyIfTEeVfbl2Qn23wHoBwacYhFGm/be60L0ar
jwO/Fk5qaUTWBV5DQAF8gBK+pNxe4phGFNdWwu6v43IG9DfVdvLVjiO9dBqsvTnS
1StqENzmnhqCYJ5+3hyU2uqAYW4DopvuYD5EgMGEfaJ3jzzlWF34Gs4OVCWUBL02
qh1Zy/4VrduuY0FRRt9foj8Ug4IvM2+a84bx4ZhW6N6BhkHOsrKaXPGf0Ng0SRUj
vH7xHelsruiE3HGc9pYZyDavXitRbvJxdF2tHD8cxpiGkUch9hTNqSaV+xkHxck6
4bAeyoVlAGKa/wyWvrdcTg==
=wVdT
-----END PGP SIGNATURE-----
Merge tag 'for-net-next-2023-12-22' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next
Luiz Augusto von Dentz says:
====================
bluetooth-next pull request for net-next:
- btnxpuart: Fix recv_buf return value
- L2CAP: Fix responding with multiple rejects
- Fix atomicity violation in {min,max}_key_size_set
- ISO: Allow binding a PA sync socket
- ISO: Reassociate a socket with an active BIS
- ISO: Avoid creating child socket if PA sync is terminating
- Add device 13d3:3572 IMC Networks Bluetooth Radio
- Don't suspend when there are connections
- Remove le_restart_scan work
- Fix bogus check for re-auth not supported with non-ssp
- lib: Add documentation to exported functions
- Support HFP offload for QCA2066
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
8a48a2dc24
|
|
@ -535,6 +535,8 @@ static int btintel_version_info_tlv(struct hci_dev *hdev,
|
|||
bt_dev_info(hdev, "%s timestamp %u.%u buildtype %u build %u", variant,
|
||||
2000 + (version->timestamp >> 8), version->timestamp & 0xff,
|
||||
version->build_type, version->build_num);
|
||||
if (version->img_type == 0x03)
|
||||
bt_dev_info(hdev, "Firmware SHA1: 0x%8.8x", version->git_sha1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -630,6 +632,9 @@ static int btintel_parse_version_tlv(struct hci_dev *hdev,
|
|||
memcpy(&version->otp_bd_addr, tlv->val,
|
||||
sizeof(bdaddr_t));
|
||||
break;
|
||||
case INTEL_TLV_GIT_SHA1:
|
||||
version->git_sha1 = get_unaligned_le32(tlv->val);
|
||||
break;
|
||||
default:
|
||||
/* Ignore rest of information */
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -41,7 +41,8 @@ enum {
|
|||
INTEL_TLV_LIMITED_CCE,
|
||||
INTEL_TLV_SBE_TYPE,
|
||||
INTEL_TLV_OTP_BDADDR,
|
||||
INTEL_TLV_UNLOCKED_STATE
|
||||
INTEL_TLV_UNLOCKED_STATE,
|
||||
INTEL_TLV_GIT_SHA1
|
||||
};
|
||||
|
||||
struct intel_tlv {
|
||||
|
|
@ -69,6 +70,7 @@ struct intel_version_tlv {
|
|||
u8 min_fw_build_yy;
|
||||
u8 limited_cce;
|
||||
u8 sbe_type;
|
||||
u32 git_sha1;
|
||||
bdaddr_t otp_bd_addr;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -336,7 +336,7 @@ mtk_stp_split(struct btmtkuart_dev *bdev, const unsigned char *data, int count,
|
|||
return data;
|
||||
}
|
||||
|
||||
static int btmtkuart_recv(struct hci_dev *hdev, const u8 *data, size_t count)
|
||||
static void btmtkuart_recv(struct hci_dev *hdev, const u8 *data, size_t count)
|
||||
{
|
||||
struct btmtkuart_dev *bdev = hci_get_drvdata(hdev);
|
||||
const unsigned char *p_left = data, *p_h4;
|
||||
|
|
@ -375,25 +375,20 @@ static int btmtkuart_recv(struct hci_dev *hdev, const u8 *data, size_t count)
|
|||
bt_dev_err(bdev->hdev,
|
||||
"Frame reassembly failed (%d)", err);
|
||||
bdev->rx_skb = NULL;
|
||||
return err;
|
||||
return;
|
||||
}
|
||||
|
||||
sz_left -= sz_h4;
|
||||
p_left += sz_h4;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int btmtkuart_receive_buf(struct serdev_device *serdev, const u8 *data,
|
||||
size_t count)
|
||||
{
|
||||
struct btmtkuart_dev *bdev = serdev_device_get_drvdata(serdev);
|
||||
int err;
|
||||
|
||||
err = btmtkuart_recv(bdev->hdev, data, count);
|
||||
if (err < 0)
|
||||
return err;
|
||||
btmtkuart_recv(bdev->hdev, data, count);
|
||||
|
||||
bdev->hdev->stat.byte_rx += count;
|
||||
|
||||
|
|
|
|||
|
|
@ -1276,11 +1276,9 @@ static int btnxpuart_receive_buf(struct serdev_device *serdev, const u8 *data,
|
|||
if (IS_ERR(nxpdev->rx_skb)) {
|
||||
int err = PTR_ERR(nxpdev->rx_skb);
|
||||
/* Safe to ignore out-of-sync bootloader signatures */
|
||||
if (is_fw_downloading(nxpdev))
|
||||
return count;
|
||||
bt_dev_err(nxpdev->hdev, "Frame reassembly failed (%d)", err);
|
||||
nxpdev->rx_skb = NULL;
|
||||
return err;
|
||||
if (!is_fw_downloading(nxpdev))
|
||||
bt_dev_err(nxpdev->hdev, "Frame reassembly failed (%d)", err);
|
||||
return count;
|
||||
}
|
||||
if (!is_fw_downloading(nxpdev))
|
||||
nxpdev->hdev->stat.byte_rx += count;
|
||||
|
|
|
|||
|
|
@ -550,6 +550,8 @@ static const struct usb_device_id quirks_table[] = {
|
|||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x13d3, 0x3571), .driver_info = BTUSB_REALTEK |
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x13d3, 0x3572), .driver_info = BTUSB_REALTEK |
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
|
||||
/* Realtek Bluetooth devices */
|
||||
{ USB_VENDOR_AND_INTERFACE_INFO(0x0bda, 0xe0, 0x01, 0x01),
|
||||
|
|
@ -4629,6 +4631,10 @@ static int btusb_suspend(struct usb_interface *intf, pm_message_t message)
|
|||
|
||||
BT_DBG("intf %p", intf);
|
||||
|
||||
/* Don't suspend if there are connections */
|
||||
if (hci_conn_count(data->hdev))
|
||||
return -EBUSY;
|
||||
|
||||
if (data->suspend_count++)
|
||||
return 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -1815,6 +1815,24 @@ static void hci_coredump_qca(struct hci_dev *hdev)
|
|||
kfree_skb(skb);
|
||||
}
|
||||
|
||||
static int qca_get_data_path_id(struct hci_dev *hdev, __u8 *data_path_id)
|
||||
{
|
||||
/* QCA uses 1 as non-HCI data path id for HFP */
|
||||
*data_path_id = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qca_configure_hfp_offload(struct hci_dev *hdev)
|
||||
{
|
||||
bt_dev_info(hdev, "HFP non-HCI data transport is supported");
|
||||
hdev->get_data_path_id = qca_get_data_path_id;
|
||||
/* Do not need to send HCI_Configure_Data_Path to configure non-HCI
|
||||
* data transport path for QCA controllers, so set below field as NULL.
|
||||
*/
|
||||
hdev->get_codec_config_data = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qca_setup(struct hci_uart *hu)
|
||||
{
|
||||
struct hci_dev *hdev = hu->hdev;
|
||||
|
|
@ -1969,6 +1987,10 @@ static int qca_setup(struct hci_uart *hu)
|
|||
hu->hdev->set_bdaddr = qca_set_bdaddr_rome;
|
||||
else
|
||||
hu->hdev->set_bdaddr = qca_set_bdaddr;
|
||||
|
||||
if (soc_type == QCA_QCA2066)
|
||||
qca_configure_hfp_offload(hdev);
|
||||
|
||||
qca->fw_version = le16_to_cpu(ver.patch_ver);
|
||||
qca->controller_id = le16_to_cpu(ver.rom_ver);
|
||||
hci_devcd_register(hdev, hci_coredump_qca, qca_dmp_hdr, NULL);
|
||||
|
|
@ -2039,6 +2061,7 @@ static const struct qca_device_data qca_soc_data_wcn3998 __maybe_unused = {
|
|||
static const struct qca_device_data qca_soc_data_qca2066 __maybe_unused = {
|
||||
.soc_type = QCA_QCA2066,
|
||||
.num_vregs = 0,
|
||||
.capabilities = QCA_CAP_WIDEBAND_SPEECH | QCA_CAP_VALID_LE_STATES,
|
||||
};
|
||||
|
||||
static const struct qca_device_data qca_soc_data_qca6390 __maybe_unused = {
|
||||
|
|
|
|||
|
|
@ -539,7 +539,6 @@ struct hci_dev {
|
|||
struct work_struct tx_work;
|
||||
|
||||
struct delayed_work le_scan_disable;
|
||||
struct delayed_work le_scan_restart;
|
||||
|
||||
struct sk_buff_head rx_q;
|
||||
struct sk_buff_head raw_q;
|
||||
|
|
@ -957,7 +956,6 @@ void hci_inquiry_cache_flush(struct hci_dev *hdev);
|
|||
/* ----- HCI Connections ----- */
|
||||
enum {
|
||||
HCI_CONN_AUTH_PEND,
|
||||
HCI_CONN_REAUTH_PEND,
|
||||
HCI_CONN_ENCRYPT_PEND,
|
||||
HCI_CONN_RSWITCH_PEND,
|
||||
HCI_CONN_MODE_CHANGE_PEND,
|
||||
|
|
@ -1297,6 +1295,30 @@ static inline struct hci_conn *hci_conn_hash_lookup_big(struct hci_dev *hdev,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static inline struct hci_conn *
|
||||
hci_conn_hash_lookup_big_state(struct hci_dev *hdev, __u8 handle, __u16 state)
|
||||
{
|
||||
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 (bacmp(&c->dst, BDADDR_ANY) || c->type != ISO_LINK ||
|
||||
c->state != state)
|
||||
continue;
|
||||
|
||||
if (handle == c->iso_qos.bcast.big) {
|
||||
rcu_read_unlock();
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline struct hci_conn *
|
||||
hci_conn_hash_lookup_pa_sync_big_handle(struct hci_dev *hdev, __u8 big)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -300,6 +300,13 @@ static int configure_datapath_sync(struct hci_dev *hdev, struct bt_codec *codec)
|
|||
__u8 vnd_len, *vnd_data = NULL;
|
||||
struct hci_op_configure_data_path *cmd = NULL;
|
||||
|
||||
if (!codec->data_path || !hdev->get_codec_config_data)
|
||||
return 0;
|
||||
|
||||
/* Do not take me as error */
|
||||
if (!hdev->get_codec_config_data)
|
||||
return 0;
|
||||
|
||||
err = hdev->get_codec_config_data(hdev, ESCO_LINK, codec, &vnd_len,
|
||||
&vnd_data);
|
||||
if (err < 0)
|
||||
|
|
@ -345,9 +352,7 @@ static int hci_enhanced_setup_sync(struct hci_dev *hdev, void *data)
|
|||
|
||||
bt_dev_dbg(hdev, "hcon %p", conn);
|
||||
|
||||
/* for offload use case, codec needs to configured before opening SCO */
|
||||
if (conn->codec.data_path)
|
||||
configure_datapath_sync(hdev, &conn->codec);
|
||||
configure_datapath_sync(hdev, &conn->codec);
|
||||
|
||||
conn->state = BT_CONNECT;
|
||||
conn->out = true;
|
||||
|
|
@ -1086,8 +1091,9 @@ static void hci_conn_cleanup_child(struct hci_conn *conn, u8 reason)
|
|||
hci_conn_failed(conn, reason);
|
||||
break;
|
||||
case ISO_LINK:
|
||||
if (conn->state != BT_CONNECTED &&
|
||||
!test_bit(HCI_CONN_CREATE_CIS, &conn->flags))
|
||||
if ((conn->state != BT_CONNECTED &&
|
||||
!test_bit(HCI_CONN_CREATE_CIS, &conn->flags)) ||
|
||||
test_bit(HCI_CONN_BIG_CREATED, &conn->flags))
|
||||
hci_conn_failed(conn, reason);
|
||||
break;
|
||||
}
|
||||
|
|
@ -2228,7 +2234,17 @@ struct hci_conn *hci_bind_bis(struct hci_dev *hdev, bdaddr_t *dst,
|
|||
__u8 base_len, __u8 *base)
|
||||
{
|
||||
struct hci_conn *conn;
|
||||
struct hci_conn *parent;
|
||||
__u8 eir[HCI_MAX_PER_AD_LENGTH];
|
||||
struct hci_link *link;
|
||||
|
||||
/* Look for any BIS that is open for rebinding */
|
||||
conn = hci_conn_hash_lookup_big_state(hdev, qos->bcast.big, BT_OPEN);
|
||||
if (conn) {
|
||||
memcpy(qos, &conn->iso_qos, sizeof(*qos));
|
||||
conn->state = BT_CONNECTED;
|
||||
return conn;
|
||||
}
|
||||
|
||||
if (base_len && base)
|
||||
base_len = eir_append_service_data(eir, 0, 0x1851,
|
||||
|
|
@ -2256,6 +2272,20 @@ struct hci_conn *hci_bind_bis(struct hci_dev *hdev, bdaddr_t *dst,
|
|||
conn->iso_qos = *qos;
|
||||
conn->state = BT_BOUND;
|
||||
|
||||
/* Link BISes together */
|
||||
parent = hci_conn_hash_lookup_big(hdev,
|
||||
conn->iso_qos.bcast.big);
|
||||
if (parent && parent != conn) {
|
||||
link = hci_conn_link(parent, conn);
|
||||
if (!link) {
|
||||
hci_conn_drop(conn);
|
||||
return ERR_PTR(-ENOLINK);
|
||||
}
|
||||
|
||||
/* Link takes the refcount */
|
||||
hci_conn_drop(conn);
|
||||
}
|
||||
|
||||
return conn;
|
||||
}
|
||||
|
||||
|
|
@ -2287,6 +2317,9 @@ struct hci_conn *hci_connect_bis(struct hci_dev *hdev, bdaddr_t *dst,
|
|||
if (IS_ERR(conn))
|
||||
return conn;
|
||||
|
||||
if (conn->state == BT_CONNECTED)
|
||||
return conn;
|
||||
|
||||
data.big = qos->bcast.big;
|
||||
data.bis = qos->bcast.bis;
|
||||
|
||||
|
|
@ -2421,12 +2454,10 @@ static int hci_conn_auth(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
|
|||
hci_send_cmd(conn->hdev, HCI_OP_AUTH_REQUESTED,
|
||||
sizeof(cp), &cp);
|
||||
|
||||
/* If we're already encrypted set the REAUTH_PEND flag,
|
||||
* otherwise set the ENCRYPT_PEND.
|
||||
/* Set the ENCRYPT_PEND to trigger encryption after
|
||||
* authentication.
|
||||
*/
|
||||
if (test_bit(HCI_CONN_ENCRYPT, &conn->flags))
|
||||
set_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
|
||||
else
|
||||
if (!test_bit(HCI_CONN_ENCRYPT, &conn->flags))
|
||||
set_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1046,10 +1046,12 @@ static int min_key_size_set(void *data, u64 val)
|
|||
{
|
||||
struct hci_dev *hdev = data;
|
||||
|
||||
if (val > hdev->le_max_key_size || val < SMP_MIN_ENC_KEY_SIZE)
|
||||
return -EINVAL;
|
||||
|
||||
hci_dev_lock(hdev);
|
||||
if (val > hdev->le_max_key_size || val < SMP_MIN_ENC_KEY_SIZE) {
|
||||
hci_dev_unlock(hdev);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
hdev->le_min_key_size = val;
|
||||
hci_dev_unlock(hdev);
|
||||
|
||||
|
|
@ -1074,10 +1076,12 @@ static int max_key_size_set(void *data, u64 val)
|
|||
{
|
||||
struct hci_dev *hdev = data;
|
||||
|
||||
if (val > SMP_MAX_ENC_KEY_SIZE || val < hdev->le_min_key_size)
|
||||
return -EINVAL;
|
||||
|
||||
hci_dev_lock(hdev);
|
||||
if (val > SMP_MAX_ENC_KEY_SIZE || val < hdev->le_min_key_size) {
|
||||
hci_dev_unlock(hdev);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
hdev->le_max_key_size = val;
|
||||
hci_dev_unlock(hdev);
|
||||
|
||||
|
|
|
|||
|
|
@ -3500,14 +3500,8 @@ static void hci_auth_complete_evt(struct hci_dev *hdev, void *data,
|
|||
|
||||
if (!ev->status) {
|
||||
clear_bit(HCI_CONN_AUTH_FAILURE, &conn->flags);
|
||||
|
||||
if (!hci_conn_ssp_enabled(conn) &&
|
||||
test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
|
||||
bt_dev_info(hdev, "re-auth of legacy device is not possible.");
|
||||
} else {
|
||||
set_bit(HCI_CONN_AUTH, &conn->flags);
|
||||
conn->sec_level = conn->pending_sec_level;
|
||||
}
|
||||
set_bit(HCI_CONN_AUTH, &conn->flags);
|
||||
conn->sec_level = conn->pending_sec_level;
|
||||
} else {
|
||||
if (ev->status == HCI_ERROR_PIN_OR_KEY_MISSING)
|
||||
set_bit(HCI_CONN_AUTH_FAILURE, &conn->flags);
|
||||
|
|
@ -3516,7 +3510,6 @@ static void hci_auth_complete_evt(struct hci_dev *hdev, void *data,
|
|||
}
|
||||
|
||||
clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
|
||||
clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
|
||||
|
||||
if (conn->state == BT_CONFIG) {
|
||||
if (!ev->status && hci_conn_ssp_enabled(conn)) {
|
||||
|
|
|
|||
|
|
@ -348,8 +348,6 @@ static void le_scan_disable(struct work_struct *work)
|
|||
if (!hci_dev_test_flag(hdev, HCI_LE_SCAN))
|
||||
goto _return;
|
||||
|
||||
cancel_delayed_work(&hdev->le_scan_restart);
|
||||
|
||||
status = hci_cmd_sync_queue(hdev, scan_disable_sync, NULL, NULL);
|
||||
if (status) {
|
||||
bt_dev_err(hdev, "failed to disable LE scan: %d", status);
|
||||
|
|
@ -397,71 +395,6 @@ static void le_scan_disable(struct work_struct *work)
|
|||
|
||||
static int hci_le_set_scan_enable_sync(struct hci_dev *hdev, u8 val,
|
||||
u8 filter_dup);
|
||||
static int hci_le_scan_restart_sync(struct hci_dev *hdev)
|
||||
{
|
||||
/* 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;
|
||||
}
|
||||
|
||||
hci_le_set_scan_enable_sync(hdev, LE_SCAN_DISABLE, 0x00);
|
||||
return hci_le_set_scan_enable_sync(hdev, LE_SCAN_ENABLE,
|
||||
LE_SCAN_FILTER_DUP_ENABLE);
|
||||
}
|
||||
|
||||
static void le_scan_restart(struct work_struct *work)
|
||||
{
|
||||
struct hci_dev *hdev = container_of(work, struct hci_dev,
|
||||
le_scan_restart.work);
|
||||
unsigned long timeout, duration, scan_start, now;
|
||||
int status;
|
||||
|
||||
bt_dev_dbg(hdev, "");
|
||||
|
||||
status = hci_le_scan_restart_sync(hdev);
|
||||
if (status) {
|
||||
bt_dev_err(hdev, "failed to restart LE scan: status %d",
|
||||
status);
|
||||
return;
|
||||
}
|
||||
|
||||
hci_dev_lock(hdev);
|
||||
|
||||
if (!test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks) ||
|
||||
!hdev->discovery.scan_start)
|
||||
goto unlock;
|
||||
|
||||
/* When the scan was started, hdev->le_scan_disable has been queued
|
||||
* after duration from scan_start. During scan restart this job
|
||||
* has been canceled, and we need to queue it again after proper
|
||||
* timeout, to make sure that scan does not run indefinitely.
|
||||
*/
|
||||
duration = hdev->discovery.scan_duration;
|
||||
scan_start = hdev->discovery.scan_start;
|
||||
now = jiffies;
|
||||
if (now - scan_start <= duration) {
|
||||
int elapsed;
|
||||
|
||||
if (now >= scan_start)
|
||||
elapsed = now - scan_start;
|
||||
else
|
||||
elapsed = ULONG_MAX - scan_start + now;
|
||||
|
||||
timeout = duration - elapsed;
|
||||
} else {
|
||||
timeout = 0;
|
||||
}
|
||||
|
||||
queue_delayed_work(hdev->req_workqueue,
|
||||
&hdev->le_scan_disable, timeout);
|
||||
|
||||
unlock:
|
||||
hci_dev_unlock(hdev);
|
||||
}
|
||||
|
||||
static int reenable_adv_sync(struct hci_dev *hdev, void *data)
|
||||
{
|
||||
|
|
@ -630,7 +563,6 @@ void hci_cmd_sync_init(struct hci_dev *hdev)
|
|||
INIT_WORK(&hdev->cmd_sync_cancel_work, hci_cmd_sync_cancel_work);
|
||||
INIT_WORK(&hdev->reenable_adv_work, reenable_adv);
|
||||
INIT_DELAYED_WORK(&hdev->le_scan_disable, le_scan_disable);
|
||||
INIT_DELAYED_WORK(&hdev->le_scan_restart, le_scan_restart);
|
||||
INIT_DELAYED_WORK(&hdev->adv_instance_expire, adv_timeout_expire);
|
||||
}
|
||||
|
||||
|
|
@ -3800,12 +3732,14 @@ static int hci_set_event_mask_sync(struct hci_dev *hdev)
|
|||
if (lmp_bredr_capable(hdev)) {
|
||||
events[4] |= 0x01; /* Flow Specification Complete */
|
||||
|
||||
/* Don't set Disconnect Complete when suspended as that
|
||||
* would wakeup the host when disconnecting due to
|
||||
* suspend.
|
||||
/* Don't set Disconnect Complete and mode change when
|
||||
* suspended as that would wakeup the host when disconnecting
|
||||
* due to suspend.
|
||||
*/
|
||||
if (hdev->suspended)
|
||||
if (hdev->suspended) {
|
||||
events[0] &= 0xef;
|
||||
events[2] &= 0xf7;
|
||||
}
|
||||
} else {
|
||||
/* Use a different default for LE-only devices */
|
||||
memset(events, 0, sizeof(events));
|
||||
|
|
@ -4960,7 +4894,6 @@ int hci_dev_close_sync(struct hci_dev *hdev)
|
|||
cancel_delayed_work(&hdev->power_off);
|
||||
cancel_delayed_work(&hdev->ncmd_timer);
|
||||
cancel_delayed_work(&hdev->le_scan_disable);
|
||||
cancel_delayed_work(&hdev->le_scan_restart);
|
||||
|
||||
hci_request_cancel_all(hdev);
|
||||
|
||||
|
|
@ -5178,7 +5111,6 @@ int hci_stop_discovery_sync(struct hci_dev *hdev)
|
|||
|
||||
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)
|
||||
|
|
@ -5686,19 +5618,18 @@ static int hci_active_scan_sync(struct hci_dev *hdev, uint16_t interval)
|
|||
if (err < 0)
|
||||
own_addr_type = ADDR_LE_DEV_PUBLIC;
|
||||
|
||||
if (hci_is_adv_monitoring(hdev)) {
|
||||
if (hci_is_adv_monitoring(hdev) ||
|
||||
(test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks) &&
|
||||
hdev->discovery.result_filtering)) {
|
||||
/* 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.
|
||||
* If controller does strict duplicate filtering and the
|
||||
* discovery requires result filtering disables controller based
|
||||
* filtering since that can cause reports that would match the
|
||||
* host filter to not be reported.
|
||||
*/
|
||||
filter_dup = LE_SCAN_FILTER_DUP_DISABLE;
|
||||
}
|
||||
|
|
@ -5778,17 +5709,6 @@ int hci_start_discovery_sync(struct hci_dev *hdev)
|
|||
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ static void iso_sock_kill(struct sock *sk);
|
|||
enum {
|
||||
BT_SK_BIG_SYNC,
|
||||
BT_SK_PA_SYNC,
|
||||
BT_SK_PA_SYNC_TERM,
|
||||
};
|
||||
|
||||
struct iso_pinfo {
|
||||
|
|
@ -82,6 +83,11 @@ static bool iso_match_sid(struct sock *sk, void *data);
|
|||
static bool iso_match_sync_handle(struct sock *sk, void *data);
|
||||
static void iso_sock_disconn(struct sock *sk);
|
||||
|
||||
typedef bool (*iso_sock_match_t)(struct sock *sk, void *data);
|
||||
|
||||
static struct sock *iso_get_sock_listen(bdaddr_t *src, bdaddr_t *dst,
|
||||
iso_sock_match_t match, void *data);
|
||||
|
||||
/* ---- ISO timers ---- */
|
||||
#define ISO_CONN_TIMEOUT (HZ * 40)
|
||||
#define ISO_DISCONN_TIMEOUT (HZ * 2)
|
||||
|
|
@ -190,10 +196,21 @@ static void iso_chan_del(struct sock *sk, int err)
|
|||
sock_set_flag(sk, SOCK_ZAPPED);
|
||||
}
|
||||
|
||||
static bool iso_match_conn_sync_handle(struct sock *sk, void *data)
|
||||
{
|
||||
struct hci_conn *hcon = data;
|
||||
|
||||
if (test_bit(BT_SK_PA_SYNC, &iso_pi(sk)->flags))
|
||||
return false;
|
||||
|
||||
return hcon->sync_handle == iso_pi(sk)->sync_handle;
|
||||
}
|
||||
|
||||
static void iso_conn_del(struct hci_conn *hcon, int err)
|
||||
{
|
||||
struct iso_conn *conn = hcon->iso_data;
|
||||
struct sock *sk;
|
||||
struct sock *parent;
|
||||
|
||||
if (!conn)
|
||||
return;
|
||||
|
|
@ -209,6 +226,25 @@ static void iso_conn_del(struct hci_conn *hcon, int err)
|
|||
|
||||
if (sk) {
|
||||
lock_sock(sk);
|
||||
|
||||
/* While a PA sync hcon is in the process of closing,
|
||||
* mark parent socket with a flag, so that any residual
|
||||
* BIGInfo adv reports that arrive before PA sync is
|
||||
* terminated are not processed anymore.
|
||||
*/
|
||||
if (test_bit(BT_SK_PA_SYNC, &iso_pi(sk)->flags)) {
|
||||
parent = iso_get_sock_listen(&hcon->src,
|
||||
&hcon->dst,
|
||||
iso_match_conn_sync_handle,
|
||||
hcon);
|
||||
|
||||
if (parent) {
|
||||
set_bit(BT_SK_PA_SYNC_TERM,
|
||||
&iso_pi(parent)->flags);
|
||||
sock_put(parent);
|
||||
}
|
||||
}
|
||||
|
||||
iso_sock_clear_timer(sk);
|
||||
iso_chan_del(sk, err);
|
||||
release_sock(sk);
|
||||
|
|
@ -545,8 +581,6 @@ static struct sock *__iso_get_sock_listen_by_sid(bdaddr_t *ba, bdaddr_t *bc,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
typedef bool (*iso_sock_match_t)(struct sock *sk, void *data);
|
||||
|
||||
/* Find socket listening:
|
||||
* source bdaddr (Unicast)
|
||||
* destination bdaddr (Broadcast only)
|
||||
|
|
@ -574,19 +608,68 @@ static struct sock *iso_get_sock_listen(bdaddr_t *src, bdaddr_t *dst,
|
|||
continue;
|
||||
|
||||
/* Exact match. */
|
||||
if (!bacmp(&iso_pi(sk)->src, src))
|
||||
if (!bacmp(&iso_pi(sk)->src, src)) {
|
||||
sock_hold(sk);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Closest match */
|
||||
if (!bacmp(&iso_pi(sk)->src, BDADDR_ANY))
|
||||
if (!bacmp(&iso_pi(sk)->src, BDADDR_ANY)) {
|
||||
if (sk1)
|
||||
sock_put(sk1);
|
||||
|
||||
sk1 = sk;
|
||||
sock_hold(sk1);
|
||||
}
|
||||
}
|
||||
|
||||
if (sk && sk1)
|
||||
sock_put(sk1);
|
||||
|
||||
read_unlock(&iso_sk_list.lock);
|
||||
|
||||
return sk ? sk : sk1;
|
||||
}
|
||||
|
||||
static struct sock *iso_get_sock_big(struct sock *match_sk, bdaddr_t *src,
|
||||
bdaddr_t *dst, uint8_t big)
|
||||
{
|
||||
struct sock *sk = NULL;
|
||||
|
||||
read_lock(&iso_sk_list.lock);
|
||||
|
||||
sk_for_each(sk, &iso_sk_list.head) {
|
||||
if (match_sk == sk)
|
||||
continue;
|
||||
|
||||
/* Look for sockets that have already been
|
||||
* connected to the BIG
|
||||
*/
|
||||
if (sk->sk_state != BT_CONNECTED &&
|
||||
sk->sk_state != BT_CONNECT)
|
||||
continue;
|
||||
|
||||
/* Match Broadcast destination */
|
||||
if (bacmp(&iso_pi(sk)->dst, dst))
|
||||
continue;
|
||||
|
||||
/* Match BIG handle */
|
||||
if (iso_pi(sk)->qos.bcast.big != big)
|
||||
continue;
|
||||
|
||||
/* Match source address */
|
||||
if (bacmp(&iso_pi(sk)->src, src))
|
||||
continue;
|
||||
|
||||
sock_hold(sk);
|
||||
break;
|
||||
}
|
||||
|
||||
read_unlock(&iso_sk_list.lock);
|
||||
|
||||
return sk;
|
||||
}
|
||||
|
||||
static void iso_sock_destruct(struct sock *sk)
|
||||
{
|
||||
BT_DBG("sk %p", sk);
|
||||
|
|
@ -639,6 +722,28 @@ static void iso_sock_kill(struct sock *sk)
|
|||
|
||||
static void iso_sock_disconn(struct sock *sk)
|
||||
{
|
||||
struct sock *bis_sk;
|
||||
struct hci_conn *hcon = iso_pi(sk)->conn->hcon;
|
||||
|
||||
if (test_bit(HCI_CONN_BIG_CREATED, &hcon->flags)) {
|
||||
bis_sk = iso_get_sock_big(sk, &iso_pi(sk)->src,
|
||||
&iso_pi(sk)->dst,
|
||||
iso_pi(sk)->qos.bcast.big);
|
||||
|
||||
/* If there are any other connected sockets for the
|
||||
* same BIG, just delete the sk and leave the bis
|
||||
* hcon active, in case later rebinding is needed.
|
||||
*/
|
||||
if (bis_sk) {
|
||||
hcon->state = BT_OPEN;
|
||||
iso_pi(sk)->conn->hcon = NULL;
|
||||
iso_sock_clear_timer(sk);
|
||||
iso_chan_del(sk, bt_to_errno(hcon->abort_reason));
|
||||
sock_put(bis_sk);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
sk->sk_state = BT_DISCONN;
|
||||
iso_sock_set_timer(sk, ISO_DISCONN_TIMEOUT);
|
||||
iso_conn_lock(iso_pi(sk)->conn);
|
||||
|
|
@ -792,27 +897,75 @@ static int iso_sock_bind_bc(struct socket *sock, struct sockaddr *addr,
|
|||
BT_DBG("sk %p bc_sid %u bc_num_bis %u", sk, sa->iso_bc->bc_sid,
|
||||
sa->iso_bc->bc_num_bis);
|
||||
|
||||
if (addr_len > sizeof(*sa) + sizeof(*sa->iso_bc))
|
||||
if (addr_len != sizeof(*sa) + sizeof(*sa->iso_bc))
|
||||
return -EINVAL;
|
||||
|
||||
bacpy(&iso_pi(sk)->dst, &sa->iso_bc->bc_bdaddr);
|
||||
|
||||
/* Check if the address type is of LE type */
|
||||
if (!bdaddr_type_is_le(sa->iso_bc->bc_bdaddr_type))
|
||||
return -EINVAL;
|
||||
|
||||
iso_pi(sk)->dst_type = sa->iso_bc->bc_bdaddr_type;
|
||||
iso_pi(sk)->sync_handle = -1;
|
||||
|
||||
if (sa->iso_bc->bc_sid > 0x0f)
|
||||
return -EINVAL;
|
||||
|
||||
iso_pi(sk)->bc_sid = sa->iso_bc->bc_sid;
|
||||
|
||||
if (sa->iso_bc->bc_num_bis > ISO_MAX_NUM_BIS)
|
||||
return -EINVAL;
|
||||
|
||||
iso_pi(sk)->bc_num_bis = sa->iso_bc->bc_num_bis;
|
||||
|
||||
for (i = 0; i < iso_pi(sk)->bc_num_bis; i++) {
|
||||
for (i = 0; i < iso_pi(sk)->bc_num_bis; i++)
|
||||
if (sa->iso_bc->bc_bis[i] < 0x01 ||
|
||||
sa->iso_bc->bc_bis[i] > 0x1f)
|
||||
return -EINVAL;
|
||||
|
||||
memcpy(iso_pi(sk)->bc_bis, sa->iso_bc->bc_bis,
|
||||
iso_pi(sk)->bc_num_bis);
|
||||
}
|
||||
memcpy(iso_pi(sk)->bc_bis, sa->iso_bc->bc_bis,
|
||||
iso_pi(sk)->bc_num_bis);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iso_sock_bind_pa_sk(struct sock *sk, struct sockaddr_iso *sa,
|
||||
int addr_len)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
if (sk->sk_type != SOCK_SEQPACKET) {
|
||||
err = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (addr_len != sizeof(*sa) + sizeof(*sa->iso_bc)) {
|
||||
err = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (sa->iso_bc->bc_num_bis > ISO_MAX_NUM_BIS) {
|
||||
err = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
iso_pi(sk)->bc_num_bis = sa->iso_bc->bc_num_bis;
|
||||
|
||||
for (int i = 0; i < iso_pi(sk)->bc_num_bis; i++)
|
||||
if (sa->iso_bc->bc_bis[i] < 0x01 ||
|
||||
sa->iso_bc->bc_bis[i] > 0x1f) {
|
||||
err = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
memcpy(iso_pi(sk)->bc_bis, sa->iso_bc->bc_bis,
|
||||
iso_pi(sk)->bc_num_bis);
|
||||
|
||||
done:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int iso_sock_bind(struct socket *sock, struct sockaddr *addr,
|
||||
int addr_len)
|
||||
{
|
||||
|
|
@ -828,6 +981,15 @@ static int iso_sock_bind(struct socket *sock, struct sockaddr *addr,
|
|||
|
||||
lock_sock(sk);
|
||||
|
||||
/* Allow the user to bind a PA sync socket to a number
|
||||
* of BISes to sync to.
|
||||
*/
|
||||
if (sk->sk_state == BT_CONNECT2 &&
|
||||
test_bit(BT_SK_PA_SYNC, &iso_pi(sk)->flags)) {
|
||||
err = iso_sock_bind_pa_sk(sk, sa, addr_len);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (sk->sk_state != BT_OPEN) {
|
||||
err = -EBADFD;
|
||||
goto done;
|
||||
|
|
@ -1694,6 +1856,7 @@ static void iso_conn_ready(struct iso_conn *conn)
|
|||
parent->sk_data_ready(parent);
|
||||
|
||||
release_sock(parent);
|
||||
sock_put(parent);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1759,9 +1922,20 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags)
|
|||
/* Try to get PA sync listening socket, if it exists */
|
||||
sk = iso_get_sock_listen(&hdev->bdaddr, bdaddr,
|
||||
iso_match_pa_sync_flag, NULL);
|
||||
if (!sk)
|
||||
|
||||
if (!sk) {
|
||||
sk = iso_get_sock_listen(&hdev->bdaddr, bdaddr,
|
||||
iso_match_sync_handle, ev2);
|
||||
|
||||
/* If PA Sync is in process of terminating,
|
||||
* do not handle any more BIGInfo adv reports.
|
||||
*/
|
||||
|
||||
if (sk && test_bit(BT_SK_PA_SYNC_TERM,
|
||||
&iso_pi(sk)->flags))
|
||||
return lm;
|
||||
}
|
||||
|
||||
if (sk) {
|
||||
int err;
|
||||
|
||||
|
|
@ -1778,6 +1952,7 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags)
|
|||
if (err) {
|
||||
bt_dev_err(hdev, "hci_le_big_create_sync: %d",
|
||||
err);
|
||||
sock_put(sk);
|
||||
sk = NULL;
|
||||
}
|
||||
}
|
||||
|
|
@ -1810,6 +1985,8 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags)
|
|||
if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags))
|
||||
*flags |= HCI_PROTO_DEFER;
|
||||
|
||||
sock_put(sk);
|
||||
|
||||
return lm;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6526,7 +6526,8 @@ static inline void l2cap_sig_channel(struct l2cap_conn *conn,
|
|||
if (len > skb->len || !cmd->ident) {
|
||||
BT_DBG("corrupted command");
|
||||
l2cap_sig_send_rej(conn, cmd->ident);
|
||||
break;
|
||||
skb_pull(skb, len > skb->len ? skb->len : len);
|
||||
continue;
|
||||
}
|
||||
|
||||
err = l2cap_bredr_sig_cmd(conn, cmd, len, skb->data);
|
||||
|
|
|
|||
|
|
@ -30,6 +30,15 @@
|
|||
|
||||
#include <net/bluetooth/bluetooth.h>
|
||||
|
||||
/**
|
||||
* baswap() - Swaps the order of a bd address
|
||||
* @dst: Pointer to a bdaddr_t struct that will store the swapped
|
||||
* bd address.
|
||||
* @src: Pointer to the bdaddr_t struct to be swapped.
|
||||
*
|
||||
* This function reverses the byte order of a Bluetooth device
|
||||
* address.
|
||||
*/
|
||||
void baswap(bdaddr_t *dst, const bdaddr_t *src)
|
||||
{
|
||||
const unsigned char *s = (const unsigned char *)src;
|
||||
|
|
@ -41,7 +50,19 @@ void baswap(bdaddr_t *dst, const bdaddr_t *src)
|
|||
}
|
||||
EXPORT_SYMBOL(baswap);
|
||||
|
||||
/* Bluetooth error codes to Unix errno mapping */
|
||||
/**
|
||||
* bt_to_errno() - Bluetooth error codes to standard errno
|
||||
* @code: Bluetooth error code to be converted
|
||||
*
|
||||
* This function takes a Bluetooth error code as input and convets
|
||||
* it to an equivalent Unix/standard errno value.
|
||||
*
|
||||
* Return:
|
||||
*
|
||||
* If the bt error code is known, an equivalent Unix errno value
|
||||
* is returned.
|
||||
* If the given bt error code is not known, ENOSYS is returned.
|
||||
*/
|
||||
int bt_to_errno(__u16 code)
|
||||
{
|
||||
switch (code) {
|
||||
|
|
@ -135,10 +156,22 @@ int bt_to_errno(__u16 code)
|
|||
}
|
||||
EXPORT_SYMBOL(bt_to_errno);
|
||||
|
||||
/* Unix errno to Bluetooth error codes mapping */
|
||||
/**
|
||||
* bt_status() - Standard errno value to Bluetooth error code
|
||||
* @err: Unix/standard errno value to be converted
|
||||
*
|
||||
* This function converts a standard/Unix errno value to an
|
||||
* equivalent Bluetooth error code.
|
||||
*
|
||||
* Return: Bluetooth error code.
|
||||
*
|
||||
* If the given errno is not found, 0x1f is returned by default
|
||||
* which indicates an unspecified error.
|
||||
* For err >= 0, no conversion is performed, and the same value
|
||||
* is immediately returned.
|
||||
*/
|
||||
__u8 bt_status(int err)
|
||||
{
|
||||
/* Don't convert if already positive value */
|
||||
if (err >= 0)
|
||||
return err;
|
||||
|
||||
|
|
@ -206,6 +239,10 @@ __u8 bt_status(int err)
|
|||
}
|
||||
EXPORT_SYMBOL(bt_status);
|
||||
|
||||
/**
|
||||
* bt_info() - Log Bluetooth information message
|
||||
* @format: Message's format string
|
||||
*/
|
||||
void bt_info(const char *format, ...)
|
||||
{
|
||||
struct va_format vaf;
|
||||
|
|
@ -222,6 +259,10 @@ void bt_info(const char *format, ...)
|
|||
}
|
||||
EXPORT_SYMBOL(bt_info);
|
||||
|
||||
/**
|
||||
* bt_warn() - Log Bluetooth warning message
|
||||
* @format: Message's format string
|
||||
*/
|
||||
void bt_warn(const char *format, ...)
|
||||
{
|
||||
struct va_format vaf;
|
||||
|
|
@ -238,6 +279,10 @@ void bt_warn(const char *format, ...)
|
|||
}
|
||||
EXPORT_SYMBOL(bt_warn);
|
||||
|
||||
/**
|
||||
* bt_err() - Log Bluetooth error message
|
||||
* @format: Message's format string
|
||||
*/
|
||||
void bt_err(const char *format, ...)
|
||||
{
|
||||
struct va_format vaf;
|
||||
|
|
@ -267,6 +312,10 @@ bool bt_dbg_get(void)
|
|||
return debug_enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* bt_dbg() - Log Bluetooth debugging message
|
||||
* @format: Message's format string
|
||||
*/
|
||||
void bt_dbg(const char *format, ...)
|
||||
{
|
||||
struct va_format vaf;
|
||||
|
|
@ -287,6 +336,13 @@ void bt_dbg(const char *format, ...)
|
|||
EXPORT_SYMBOL(bt_dbg);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* bt_warn_ratelimited() - Log rate-limited Bluetooth warning message
|
||||
* @format: Message's format string
|
||||
*
|
||||
* This functions works like bt_warn, but it uses rate limiting
|
||||
* to prevent the message from being logged too often.
|
||||
*/
|
||||
void bt_warn_ratelimited(const char *format, ...)
|
||||
{
|
||||
struct va_format vaf;
|
||||
|
|
@ -303,6 +359,13 @@ void bt_warn_ratelimited(const char *format, ...)
|
|||
}
|
||||
EXPORT_SYMBOL(bt_warn_ratelimited);
|
||||
|
||||
/**
|
||||
* bt_err_ratelimited() - Log rate-limited Bluetooth error message
|
||||
* @format: Message's format string
|
||||
*
|
||||
* This functions works like bt_err, but it uses rate limiting
|
||||
* to prevent the message from being logged too often.
|
||||
*/
|
||||
void bt_err_ratelimited(const char *format, ...)
|
||||
{
|
||||
struct va_format vaf;
|
||||
|
|
|
|||
|
|
@ -10145,21 +10145,6 @@ static bool eir_has_uuids(u8 *eir, u16 eir_len, u16 uuid_count, u8 (*uuids)[16])
|
|||
return false;
|
||||
}
|
||||
|
||||
static void restart_le_scan(struct hci_dev *hdev)
|
||||
{
|
||||
/* If controller is not scanning we are done. */
|
||||
if (!hci_dev_test_flag(hdev, HCI_LE_SCAN))
|
||||
return;
|
||||
|
||||
if (time_after(jiffies + DISCOV_LE_RESTART_DELAY,
|
||||
hdev->discovery.scan_start +
|
||||
hdev->discovery.scan_duration))
|
||||
return;
|
||||
|
||||
queue_delayed_work(hdev->req_workqueue, &hdev->le_scan_restart,
|
||||
DISCOV_LE_RESTART_DELAY);
|
||||
}
|
||||
|
||||
static bool is_filter_match(struct hci_dev *hdev, s8 rssi, u8 *eir,
|
||||
u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
|
||||
{
|
||||
|
|
@ -10194,8 +10179,6 @@ static bool is_filter_match(struct hci_dev *hdev, s8 rssi, u8 *eir,
|
|||
* scanning to ensure updated result with updated RSSI values.
|
||||
*/
|
||||
if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks)) {
|
||||
restart_le_scan(hdev);
|
||||
|
||||
/* Validate RSSI value against the RSSI threshold once more. */
|
||||
if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
|
||||
rssi < hdev->discovery.rssi)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user