bluetooth-next pull request for net-next:

- Add support for Realtek 8761BUV
  - Add HCI_QUIRK_BROKEN_ENHANCED_SETUP_SYNC_CONN quirk
  - Add support for RTL8852C
  - Add a new PID/VID 0489/e0c8 for MT7921
  - Add support for Qualcomm WCN785x
 -----BEGIN PGP SIGNATURE-----
 
 iQJNBAABCAA3FiEE7E6oRXp8w05ovYr/9JCA4xAyCykFAmKL8N4ZHGx1aXoudm9u
 LmRlbnR6QGludGVsLmNvbQAKCRD0kIDjEDILKfy6EACPSdWECxGv+20lpBmgRbfF
 1Ahu2rFfEtK5iDaTiFLqBOczGkaYnhjq9/Er4VsYHMH1DVedOKoTskzfa2V68j0L
 xyCU44E0x314YI/B2sWoMAYejkPX265r0292KzZUpXM2s+S0Doh3Z52glMrjh13C
 GbaTfukocBZ6HNIiXp8xQLIaD6MbKGhs2VSWuoXLQqASujrixm1ucglsHNbjfL6e
 huSL/SoxKukX8qhlO19pJniROLKq0aC5tQSk66ihvhHWlNBTNJYkg6HoJ8vrB81d
 lBjVjPjElbTljQIC+PeOSCSeOn+ELizsUdGgWxiZ2fgzgQvko0fDSnGSnpRSCnNH
 zxSBs/pn3cgVS6rSIIzFXsnhdBgAoiwqqhwy+bKsi3nnIXGriZMn82Dpr7z/+QWB
 di2wKlZSXw8LEhDaBxi8espe1NkdhgSYWI8c2hh40PLkydBpGXwag9FBkMM4cgsU
 4p/riOd776EEVtwXI+lDcAdMFcbMLTf094qZWi1of93VUgDPoy8TSy3ZdshupZah
 8UQyeKKYb3lxXIXd/i6C/jhYgPvo/8ZWv+OwysPpAzvvyhAagEKS1czSGJ01yjsy
 1k+ebPY4CIHBBT23UFYKxD6Tgn9SAiqKtf0XtbYzCV2UD+QtUadc8MeGFtYb+0j1
 ybtkiTT++lU3M9KfAMtH8A==
 =XFUz
 -----END PGP SIGNATURE-----

Merge tag 'for-net-next-2022-05-23' 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:

 - Add support for Realtek 8761BUV
 - Add HCI_QUIRK_BROKEN_ENHANCED_SETUP_SYNC_CONN quirk
 - Add support for RTL8852C
 - Add a new PID/VID 0489/e0c8 for MT7921
 - Add support for Qualcomm WCN785x

* tag 'for-net-next-2022-05-23' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next: (26 commits)
  Bluetooth: hci_sync: use hci_skb_event() helper
  Bluetooth: eir: Add helpers for managing service data
  Bluetooth: hci_sync: Fix attempting to suspend with unfiltered passive scan
  Bluetooth: MGMT: Add conditions for setting HCI_CONN_FLAG_REMOTE_WAKEUP
  Bluetooth: btmtksdio: fix the reset takes too long
  Bluetooth: btmtksdio: fix possible FW initialization failure
  Bluetooth: btmtksdio: fix use-after-free at btmtksdio_recv_event
  Bluetooth: btbcm: Add entry for BCM4373A0 UART Bluetooth
  Bluetooth: btusb: Add a new PID/VID 0489/e0c8 for MT7921
  Bluetooth: btusb: Add 0x0bda:0x8771 Realtek 8761BUV devices
  Bluetooth: btusb: Set HCI_QUIRK_BROKEN_ERR_DATA_REPORTING for QCA
  Bluetooth: core: Fix missing power_on work cancel on HCI close
  Bluetooth: btusb: add support for Qualcomm WCN785x
  Bluetooth: protect le accept and resolv lists with hdev->lock
  Bluetooth: use hdev lock for accept_list and reject_list in conn req
  Bluetooth: use hdev lock in activate_scan for hci_is_adv_monitoring
  Bluetooth: btrtl: Add support for RTL8852C
  Bluetooth: btusb: Set HCI_QUIRK_BROKEN_ENHANCED_SETUP_SYNC_CONN for QCA
  Bluetooth: Print broken quirks
  Bluetooth: HCI: Add HCI_QUIRK_BROKEN_ENHANCED_SETUP_SYNC_CONN quirk
  ...
====================

Link: https://lore.kernel.org/r/20220523204151.3327345-1-luiz.dentz@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski 2022-05-23 14:36:36 -07:00
commit b1e6738a21
18 changed files with 289 additions and 53 deletions

View file

@ -9,6 +9,7 @@
#include <linux/module.h>
#include <linux/firmware.h>
#include <linux/dmi.h>
#include <linux/of.h>
#include <asm/unaligned.h>
#include <net/bluetooth/bluetooth.h>
@ -29,7 +30,7 @@
#define BDADDR_BCM43341B (&(bdaddr_t) {{0xac, 0x1f, 0x00, 0x1b, 0x34, 0x43}})
#define BCM_FW_NAME_LEN 64
#define BCM_FW_NAME_COUNT_MAX 2
#define BCM_FW_NAME_COUNT_MAX 4
/* For kmalloc-ing the fw-name array instead of putting it on the stack */
typedef char bcm_fw_name[BCM_FW_NAME_LEN];
@ -457,6 +458,7 @@ static const struct bcm_subver_table bcm_uart_subver_table[] = {
{ 0x6106, "BCM4359C0" }, /* 003.001.006 */
{ 0x4106, "BCM4335A0" }, /* 002.001.006 */
{ 0x410c, "BCM43430B0" }, /* 002.001.012 */
{ 0x2119, "BCM4373A0" }, /* 001.001.025 */
{ }
};
@ -476,6 +478,42 @@ static const struct bcm_subver_table bcm_usb_subver_table[] = {
{ }
};
/*
* This currently only looks up the device tree board appendix,
* but can be expanded to other mechanisms.
*/
static const char *btbcm_get_board_name(struct device *dev)
{
#ifdef CONFIG_OF
struct device_node *root;
char *board_type;
const char *tmp;
int len;
int i;
root = of_find_node_by_path("/");
if (!root)
return NULL;
if (of_property_read_string_index(root, "compatible", 0, &tmp))
return NULL;
/* get rid of any '/' in the compatible string */
len = strlen(tmp) + 1;
board_type = devm_kzalloc(dev, len, GFP_KERNEL);
strscpy(board_type, tmp, len);
for (i = 0; i < board_type[i]; i++) {
if (board_type[i] == '/')
board_type[i] = '-';
}
of_node_put(root);
return board_type;
#else
return NULL;
#endif
}
int btbcm_initialize(struct hci_dev *hdev, bool *fw_load_done)
{
u16 subver, rev, pid, vid;
@ -483,12 +521,15 @@ int btbcm_initialize(struct hci_dev *hdev, bool *fw_load_done)
struct hci_rp_read_local_version *ver;
const struct bcm_subver_table *bcm_subver_table;
const char *hw_name = NULL;
const char *board_name;
char postfix[16] = "";
int fw_name_count = 0;
bcm_fw_name *fw_name;
const struct firmware *fw;
int i, err;
board_name = btbcm_get_board_name(&hdev->dev);
/* Reset */
err = btbcm_reset(hdev);
if (err)
@ -549,11 +590,21 @@ int btbcm_initialize(struct hci_dev *hdev, bool *fw_load_done)
return -ENOMEM;
if (hw_name) {
if (board_name) {
snprintf(fw_name[fw_name_count], BCM_FW_NAME_LEN,
"brcm/%s%s.%s.hcd", hw_name, postfix, board_name);
fw_name_count++;
}
snprintf(fw_name[fw_name_count], BCM_FW_NAME_LEN,
"brcm/%s%s.hcd", hw_name, postfix);
fw_name_count++;
}
if (board_name) {
snprintf(fw_name[fw_name_count], BCM_FW_NAME_LEN,
"brcm/BCM%s.%s.hcd", postfix, board_name);
fw_name_count++;
}
snprintf(fw_name[fw_name_count], BCM_FW_NAME_LEN,
"brcm/BCM%s.hcd", postfix);
fw_name_count++;

View file

@ -794,7 +794,7 @@ static void regmap_ibt_free_context(void *context)
kfree(context);
}
static struct regmap_bus regmap_ibt = {
static const struct regmap_bus regmap_ibt = {
.read = regmap_ibt_read,
.write = regmap_ibt_write,
.gather_write = regmap_ibt_gather_write,

View file

@ -379,6 +379,7 @@ static int btmtksdio_recv_event(struct hci_dev *hdev, struct sk_buff *skb)
{
struct btmtksdio_dev *bdev = hci_get_drvdata(hdev);
struct hci_event_hdr *hdr = (void *)skb->data;
u8 evt = hdr->evt;
int err;
/* When someone waits for the WMT event, the skb is being cloned
@ -396,7 +397,7 @@ static int btmtksdio_recv_event(struct hci_dev *hdev, struct sk_buff *skb)
if (err < 0)
goto err_free_skb;
if (hdr->evt == HCI_EV_WMT) {
if (evt == HCI_EV_WMT) {
if (test_and_clear_bit(BTMTKSDIO_TX_WAIT_VND_EVT,
&bdev->tx_state)) {
/* Barrier to sync with other CPUs */
@ -863,6 +864,14 @@ static int mt79xx_setup(struct hci_dev *hdev, const char *fwname)
return err;
}
err = btmtksdio_fw_pmctrl(bdev);
if (err < 0)
return err;
err = btmtksdio_drv_pmctrl(bdev);
if (err < 0)
return err;
/* Enable Bluetooth protocol */
wmt_params.op = BTMTK_WMT_FUNC_CTRL;
wmt_params.flag = 0;
@ -961,7 +970,7 @@ static int btmtksdio_get_codec_config_data(struct hci_dev *hdev,
}
*ven_data = kmalloc(sizeof(__u8), GFP_KERNEL);
if (!ven_data) {
if (!*ven_data) {
err = -ENOMEM;
goto error;
}
@ -1108,14 +1117,6 @@ static int btmtksdio_setup(struct hci_dev *hdev)
if (err < 0)
return err;
err = btmtksdio_fw_pmctrl(bdev);
if (err < 0)
return err;
err = btmtksdio_drv_pmctrl(bdev);
if (err < 0)
return err;
/* Enable SCO over I2S/PCM */
err = btmtksdio_sco_setting(hdev);
if (err < 0) {
@ -1188,6 +1189,10 @@ static int btmtksdio_shutdown(struct hci_dev *hdev)
*/
pm_runtime_get_sync(bdev->dev);
/* wmt command only works until the reset is complete */
if (test_bit(BTMTKSDIO_HW_RESET_ACTIVE, &bdev->tx_state))
goto ignore_wmt_cmd;
/* Disable the device */
wmt_params.op = BTMTK_WMT_FUNC_CTRL;
wmt_params.flag = 0;
@ -1201,6 +1206,7 @@ static int btmtksdio_shutdown(struct hci_dev *hdev)
return err;
}
ignore_wmt_cmd:
pm_runtime_put_noidle(bdev->dev);
pm_runtime_disable(bdev->dev);

View file

@ -50,6 +50,7 @@ enum btrtl_chip_id {
CHIP_ID_8761B,
CHIP_ID_8852A = 18,
CHIP_ID_8852B = 20,
CHIP_ID_8852C = 25,
};
struct id_table {
@ -196,6 +197,14 @@ static const struct id_table ic_id_table[] = {
.has_msft_ext = true,
.fw_name = "rtl_bt/rtl8852bu_fw.bin",
.cfg_name = "rtl_bt/rtl8852bu_config" },
/* 8852C */
{ IC_INFO(RTL_ROM_LMP_8852A, 0xc, 0xc, HCI_USB),
.config_needed = false,
.has_rom_version = true,
.has_msft_ext = true,
.fw_name = "rtl_bt/rtl8852cu_fw.bin",
.cfg_name = "rtl_bt/rtl8852cu_config" },
};
static const struct id_table *btrtl_match_ic(u16 lmp_subver, u16 hci_rev,
@ -305,6 +314,7 @@ static int rtlbt_parse_firmware(struct hci_dev *hdev,
{ RTL_ROM_LMP_8761A, 14 }, /* 8761B */
{ RTL_ROM_LMP_8852A, 18 }, /* 8852A */
{ RTL_ROM_LMP_8852A, 20 }, /* 8852B */
{ RTL_ROM_LMP_8852A, 25 }, /* 8852C */
};
min_size = sizeof(struct rtl_epatch_header) + sizeof(extension_sig) + 3;
@ -768,6 +778,7 @@ void btrtl_set_quirks(struct hci_dev *hdev, struct btrtl_device_info *btrtl_dev)
case CHIP_ID_8822C:
case CHIP_ID_8852A:
case CHIP_ID_8852B:
case CHIP_ID_8852C:
set_bit(HCI_QUIRK_VALID_LE_STATES, &hdev->quirks);
set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks);
hci_set_aosp_capable(hdev);
@ -947,3 +958,5 @@ MODULE_FIRMWARE("rtl_bt/rtl8852au_fw.bin");
MODULE_FIRMWARE("rtl_bt/rtl8852au_config.bin");
MODULE_FIRMWARE("rtl_bt/rtl8852bu_fw.bin");
MODULE_FIRMWARE("rtl_bt/rtl8852bu_config.bin");
MODULE_FIRMWARE("rtl_bt/rtl8852cu_fw.bin");
MODULE_FIRMWARE("rtl_bt/rtl8852cu_config.bin");

View file

@ -317,6 +317,11 @@ static const struct usb_device_id blacklist_table[] = {
BTUSB_WIDEBAND_SPEECH |
BTUSB_VALID_LE_STATES },
/* QCA WCN785x chipset */
{ USB_DEVICE(0x0cf3, 0xe700), .driver_info = BTUSB_QCA_WCN6855 |
BTUSB_WIDEBAND_SPEECH |
BTUSB_VALID_LE_STATES },
/* Broadcom BCM2035 */
{ USB_DEVICE(0x0a5c, 0x2009), .driver_info = BTUSB_BCM92035 },
{ USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU },
@ -446,6 +451,9 @@ static const struct usb_device_id blacklist_table[] = {
BTUSB_VALID_LE_STATES },
/* Additional MediaTek MT7921 Bluetooth devices */
{ USB_DEVICE(0x0489, 0xe0c8), .driver_info = BTUSB_MEDIATEK |
BTUSB_WIDEBAND_SPEECH |
BTUSB_VALID_LE_STATES },
{ USB_DEVICE(0x04ca, 0x3802), .driver_info = BTUSB_MEDIATEK |
BTUSB_WIDEBAND_SPEECH |
BTUSB_VALID_LE_STATES },
@ -500,6 +508,10 @@ static const struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x2550, 0x8761), .driver_info = BTUSB_REALTEK |
BTUSB_WIDEBAND_SPEECH },
/* Additional Realtek 8761BUV Bluetooth devices */
{ USB_DEVICE(0x0bda, 0x8771), .driver_info = BTUSB_REALTEK |
BTUSB_WIDEBAND_SPEECH },
/* Additional Realtek 8821AE Bluetooth devices */
{ USB_DEVICE(0x0b05, 0x17dc), .driver_info = BTUSB_REALTEK },
{ USB_DEVICE(0x13d3, 0x3414), .driver_info = BTUSB_REALTEK },
@ -3037,6 +3049,7 @@ static const struct qca_device_info qca_devices_table[] = {
{ 0x00130100, 40, 4, 16 }, /* WCN6855 1.0 */
{ 0x00130200, 40, 4, 16 }, /* WCN6855 2.0 */
{ 0x00130201, 40, 4, 16 }, /* WCN6855 2.1 */
{ 0x00190200, 40, 4, 16 }, /* WCN785x 2.0 */
};
static int btusb_qca_send_vendor_req(struct usb_device *udev, u8 request,
@ -3327,14 +3340,20 @@ static int btusb_setup_qca(struct hci_dev *hdev)
if (err < 0)
return err;
/* WCN6855 2.1 will reset to apply firmware downloaded here, so
/* WCN6855 2.1 and later will reset to apply firmware downloaded here, so
* wait ~100ms for reset Done then go ahead, otherwise, it maybe
* cause potential enable failure.
*/
if (info->rom_version == 0x00130201)
if (info->rom_version >= 0x00130201)
msleep(QCA_BT_RESET_WAIT_MS);
}
/* Mark HCI_OP_ENHANCED_SETUP_SYNC_CONN as broken as it doesn't seem to
* work with the likes of HSP/HFP mSBC.
*/
set_bit(HCI_QUIRK_BROKEN_ENHANCED_SETUP_SYNC_CONN, &hdev->quirks);
set_bit(HCI_QUIRK_BROKEN_ERR_DATA_REPORTING, &hdev->quirks);
return 0;
}

View file

@ -696,9 +696,9 @@ static int qca_close(struct hci_uart *hu)
skb_queue_purge(&qca->tx_wait_q);
skb_queue_purge(&qca->txq);
skb_queue_purge(&qca->rx_memdump_q);
del_timer(&qca->tx_idle_timer);
del_timer(&qca->wake_retrans_timer);
destroy_workqueue(qca->workqueue);
del_timer_sync(&qca->tx_idle_timer);
del_timer_sync(&qca->wake_retrans_timer);
qca->hu = NULL;
kfree_skb(qca->rx_skb);

View file

@ -265,6 +265,15 @@ enum {
* runtime suspend, because event filtering takes place there.
*/
HCI_QUIRK_BROKEN_FILTER_CLEAR_ALL,
/*
* When this quirk is set, disables the use of
* HCI_OP_ENHANCED_SETUP_SYNC_CONN command to setup SCO connections.
*
* This quirk can be set before hci_register_dev is called or
* during the hdev->setup vendor callback.
*/
HCI_QUIRK_BROKEN_ENHANCED_SETUP_SYNC_CONN,
};
/* HCI device flags */
@ -616,6 +625,7 @@ enum {
#define EIR_SSP_RAND_R192 0x0F /* Simple Pairing Randomizer R-192 */
#define EIR_DEVICE_ID 0x10 /* device ID */
#define EIR_APPEARANCE 0x19 /* Device appearance */
#define EIR_SERVICE_DATA 0x16 /* Service Data */
#define EIR_LE_BDADDR 0x1B /* LE Bluetooth device address */
#define EIR_LE_ROLE 0x1C /* LE role */
#define EIR_SSP_HASH_C256 0x1D /* Simple Pairing Hash C-256 */

View file

@ -1495,8 +1495,12 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
#define privacy_mode_capable(dev) (use_ll_privacy(dev) && \
(hdev->commands[39] & 0x04))
/* Use enhanced synchronous connection if command is supported */
#define enhanced_sco_capable(dev) ((dev)->commands[29] & 0x08)
/* Use enhanced synchronous connection if command is supported and its quirk
* has not been set.
*/
#define enhanced_sync_conn_capable(dev) \
(((dev)->commands[29] & 0x08) && \
!test_bit(HCI_QUIRK_BROKEN_ENHANCED_SETUP_SYNC_CONN, &(dev)->quirks))
/* Use ext scanning if set ext scan param and ext scan enable is supported */
#define use_ext_scan(dev) (((dev)->commands[37] & 0x20) && \

View file

@ -55,6 +55,19 @@ u8 eir_append_appearance(struct hci_dev *hdev, u8 *ptr, u8 ad_len)
return eir_append_le16(ptr, ad_len, EIR_APPEARANCE, hdev->appearance);
}
u8 eir_append_service_data(u8 *eir, u16 eir_len, u16 uuid, u8 *data,
u8 data_len)
{
eir[eir_len++] = sizeof(u8) + sizeof(uuid) + data_len;
eir[eir_len++] = EIR_SERVICE_DATA;
put_unaligned_le16(uuid, &eir[eir_len]);
eir_len += sizeof(uuid);
memcpy(&eir[eir_len], data, data_len);
eir_len += data_len;
return eir_len;
}
static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
{
u8 *ptr = data, *uuids_start = NULL;
@ -333,3 +346,21 @@ u8 eir_create_scan_rsp(struct hci_dev *hdev, u8 instance, u8 *ptr)
return scan_rsp_len;
}
void *eir_get_service_data(u8 *eir, size_t eir_len, u16 uuid, size_t *len)
{
while ((eir = eir_get_data(eir, eir_len, EIR_SERVICE_DATA, len))) {
u16 value = get_unaligned_le16(eir);
if (uuid == value) {
if (len)
*len -= 2;
return &eir[2];
}
eir += *len;
eir_len -= *len;
}
return NULL;
}

View file

@ -14,6 +14,8 @@ u8 eir_create_scan_rsp(struct hci_dev *hdev, u8 instance, u8 *ptr);
u8 eir_append_local_name(struct hci_dev *hdev, u8 *eir, u8 ad_len);
u8 eir_append_appearance(struct hci_dev *hdev, u8 *ptr, u8 ad_len);
u8 eir_append_service_data(u8 *eir, u16 eir_len, u16 uuid, u8 *data,
u8 data_len);
static inline u16 eir_precalc_len(u8 data_len)
{
@ -92,3 +94,5 @@ static inline void *eir_get_data(u8 *eir, size_t eir_len, u8 type,
return NULL;
}
void *eir_get_service_data(u8 *eir, size_t eir_len, u16 uuid, size_t *len);

View file

@ -481,7 +481,7 @@ static bool hci_setup_sync_conn(struct hci_conn *conn, __u16 handle)
bool hci_setup_sync(struct hci_conn *conn, __u16 handle)
{
if (enhanced_sco_capable(conn->hdev))
if (enhanced_sync_conn_capable(conn->hdev))
return hci_enhanced_setup_sync_conn(conn, handle);
return hci_setup_sync_conn(conn, handle);

View file

@ -2675,8 +2675,6 @@ void hci_unregister_dev(struct hci_dev *hdev)
list_del(&hdev->list);
write_unlock(&hci_dev_list_lock);
cancel_work_sync(&hdev->power_on);
hci_cmd_sync_clear(hdev);
if (!test_bit(HCI_QUIRK_NO_SUSPEND_NOTIFIER, &hdev->quirks))

View file

@ -1835,7 +1835,9 @@ static u8 hci_cc_le_clear_accept_list(struct hci_dev *hdev, void *data,
if (rp->status)
return rp->status;
hci_dev_lock(hdev);
hci_bdaddr_list_clear(&hdev->le_accept_list);
hci_dev_unlock(hdev);
return rp->status;
}
@ -1855,8 +1857,10 @@ static u8 hci_cc_le_add_to_accept_list(struct hci_dev *hdev, void *data,
if (!sent)
return rp->status;
hci_dev_lock(hdev);
hci_bdaddr_list_add(&hdev->le_accept_list, &sent->bdaddr,
sent->bdaddr_type);
hci_dev_unlock(hdev);
return rp->status;
}
@ -1876,8 +1880,10 @@ static u8 hci_cc_le_del_from_accept_list(struct hci_dev *hdev, void *data,
if (!sent)
return rp->status;
hci_dev_lock(hdev);
hci_bdaddr_list_del(&hdev->le_accept_list, &sent->bdaddr,
sent->bdaddr_type);
hci_dev_unlock(hdev);
return rp->status;
}
@ -1949,9 +1955,11 @@ static u8 hci_cc_le_add_to_resolv_list(struct hci_dev *hdev, void *data,
if (!sent)
return rp->status;
hci_dev_lock(hdev);
hci_bdaddr_list_add_with_irk(&hdev->le_resolv_list, &sent->bdaddr,
sent->bdaddr_type, sent->peer_irk,
sent->local_irk);
hci_dev_unlock(hdev);
return rp->status;
}
@ -1971,8 +1979,10 @@ static u8 hci_cc_le_del_from_resolv_list(struct hci_dev *hdev, void *data,
if (!sent)
return rp->status;
hci_dev_lock(hdev);
hci_bdaddr_list_del_with_irk(&hdev->le_resolv_list, &sent->bdaddr,
sent->bdaddr_type);
hci_dev_unlock(hdev);
return rp->status;
}
@ -1987,7 +1997,9 @@ static u8 hci_cc_le_clear_resolv_list(struct hci_dev *hdev, void *data,
if (rp->status)
return rp->status;
hci_dev_lock(hdev);
hci_bdaddr_list_clear(&hdev->le_resolv_list);
hci_dev_unlock(hdev);
return rp->status;
}
@ -3225,10 +3237,12 @@ static void hci_conn_request_evt(struct hci_dev *hdev, void *data,
return;
}
hci_dev_lock(hdev);
if (hci_bdaddr_list_lookup(&hdev->reject_list, &ev->bdaddr,
BDADDR_BREDR)) {
hci_reject_conn(hdev, &ev->bdaddr);
return;
goto unlock;
}
/* Require HCI_CONNECTABLE or an accept list entry to accept the
@ -3240,13 +3254,11 @@ static void hci_conn_request_evt(struct hci_dev *hdev, void *data,
!hci_bdaddr_list_lookup_with_flags(&hdev->accept_list, &ev->bdaddr,
BDADDR_BREDR)) {
hci_reject_conn(hdev, &ev->bdaddr);
return;
goto unlock;
}
/* Connection accepted */
hci_dev_lock(hdev);
ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
if (ie)
memcpy(ie->data.dev_class, ev->dev_class, 3);
@ -3258,8 +3270,7 @@ static void hci_conn_request_evt(struct hci_dev *hdev, void *data,
HCI_ROLE_SLAVE);
if (!conn) {
bt_dev_err(hdev, "no memory for new connection");
hci_dev_unlock(hdev);
return;
goto unlock;
}
}
@ -3299,6 +3310,10 @@ static void hci_conn_request_evt(struct hci_dev *hdev, void *data,
conn->state = BT_CONNECT2;
hci_connect_cfm(conn, 0);
}
return;
unlock:
hci_dev_unlock(hdev);
}
static u8 hci_to_mgmt_reason(u8 err)

View file

@ -261,7 +261,7 @@ void hci_req_add_ev(struct hci_request *req, u16 opcode, u32 plen,
if (skb_queue_empty(&req->cmd_q))
bt_cb(skb)->hci.req_flags |= HCI_REQ_START;
bt_cb(skb)->hci.req_event = event;
hci_skb_event(skb) = event;
skb_queue_tail(&req->cmd_q, skb);
}
@ -2260,6 +2260,7 @@ static int active_scan(struct hci_request *req, unsigned long opt)
if (err < 0)
own_addr_type = ADDR_LE_DEV_PUBLIC;
hci_dev_lock(hdev);
if (hci_is_adv_monitoring(hdev)) {
/* Duplicate filter should be disabled when some advertisement
* monitor is activated, otherwise AdvMon can only receive one
@ -2276,6 +2277,7 @@ static int active_scan(struct hci_request *req, unsigned long opt)
*/
filter_dup = LE_SCAN_FILTER_DUP_DISABLE;
}
hci_dev_unlock(hdev);
hci_req_start_scan(req, LE_SCAN_ACTIVE, interval,
hdev->le_scan_window_discovery, own_addr_type,

View file

@ -1664,20 +1664,19 @@ static int hci_le_add_accept_list_sync(struct hci_dev *hdev,
struct hci_cp_le_add_to_accept_list cp;
int err;
/* During suspend, only wakeable devices can be in acceptlist */
if (hdev->suspended &&
!test_bit(HCI_CONN_FLAG_REMOTE_WAKEUP, params->flags))
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 */
if (!use_ll_privacy(hdev) &&
hci_find_irk_by_addr(hdev, &params->addr, params->addr_type)) {
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 &&
!test_bit(HCI_CONN_FLAG_REMOTE_WAKEUP, params->flags))
return 0;
/* Attempt to program the device in the resolving list first to avoid
* having to rollback in case it fails since the resolving list is
@ -3825,6 +3824,30 @@ static int hci_init_sync(struct hci_dev *hdev)
return 0;
}
#define HCI_QUIRK_BROKEN(_quirk, _desc) { HCI_QUIRK_BROKEN_##_quirk, _desc }
static const struct {
unsigned long quirk;
const char *desc;
} hci_broken_table[] = {
HCI_QUIRK_BROKEN(LOCAL_COMMANDS,
"HCI Read Local Supported Commands not supported"),
HCI_QUIRK_BROKEN(STORED_LINK_KEY,
"HCI Delete Stored Link Key command is advertised, "
"but not supported."),
HCI_QUIRK_BROKEN(ERR_DATA_REPORTING,
"HCI Read Default Erroneous Data Reporting command is "
"advertised, but not supported."),
HCI_QUIRK_BROKEN(READ_TRANSMIT_POWER,
"HCI Read Transmit Power Level command is advertised, "
"but not supported."),
HCI_QUIRK_BROKEN(FILTER_CLEAR_ALL,
"HCI Set Event Filter command not supported."),
HCI_QUIRK_BROKEN(ENHANCED_SETUP_SYNC_CONN,
"HCI Enhanced Setup Synchronous Connection command is "
"advertised, but not supported.")
};
int hci_dev_open_sync(struct hci_dev *hdev)
{
int ret = 0;
@ -3886,12 +3909,19 @@ int hci_dev_open_sync(struct hci_dev *hdev)
if (hci_dev_test_flag(hdev, HCI_SETUP) ||
test_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks)) {
bool invalid_bdaddr;
size_t i;
hci_sock_dev_event(hdev, HCI_DEV_SETUP);
if (hdev->setup)
ret = hdev->setup(hdev);
for (i = 0; i < ARRAY_SIZE(hci_broken_table); i++) {
if (test_bit(hci_broken_table[i].quirk, &hdev->quirks))
bt_dev_warn(hdev, "%s",
hci_broken_table[i].desc);
}
/* The transport driver can set the quirk to mark the
* BD_ADDR invalid before creating the HCI device or in
* its setup callback.
@ -4058,6 +4088,7 @@ int hci_dev_close_sync(struct hci_dev *hdev)
bt_dev_dbg(hdev, "");
cancel_work_sync(&hdev->power_on);
cancel_delayed_work(&hdev->power_off);
cancel_delayed_work(&hdev->ncmd_timer);
@ -4881,10 +4912,28 @@ static int hci_update_event_filter_sync(struct hci_dev *hdev)
return 0;
}
/* This function disables scan (BR and LE) and mark it as paused */
static int hci_pause_scan_sync(struct hci_dev *hdev)
{
if (hdev->scanning_paused)
return 0;
/* Disable page scan if enabled */
if (test_bit(HCI_PSCAN, &hdev->flags))
hci_write_scan_enable_sync(hdev, SCAN_DISABLED);
hci_scan_disable_sync(hdev);
hdev->scanning_paused = true;
return 0;
}
/* This function performs the HCI suspend procedures in the follow order:
*
* Pause discovery (active scanning/inquiry)
* Pause Directed Advertising/Advertising
* Pause Scanning (passive scanning in case discovery was not active)
* Disconnect all connections
* Set suspend_status to BT_SUSPEND_DISCONNECT if hdev cannot wakeup
* otherwise:
@ -4910,15 +4959,11 @@ int hci_suspend_sync(struct hci_dev *hdev)
/* Pause other advertisements */
hci_pause_advertising_sync(hdev);
/* Disable page scan if enabled */
if (test_bit(HCI_PSCAN, &hdev->flags))
hci_write_scan_enable_sync(hdev, SCAN_DISABLED);
/* Suspend monitor filters */
hci_suspend_monitor_sync(hdev);
/* Prevent disconnects from causing scanning to be re-enabled */
hdev->scanning_paused = true;
hci_pause_scan_sync(hdev);
/* Soft disconnect everything (power off) */
err = hci_disconnect_all_sync(hdev, HCI_ERROR_REMOTE_POWER_OFF);
@ -4989,6 +5034,22 @@ static void hci_resume_monitor_sync(struct hci_dev *hdev)
}
}
/* This function resume scan and reset paused flag */
static int hci_resume_scan_sync(struct hci_dev *hdev)
{
if (!hdev->scanning_paused)
return 0;
hci_update_scan_sync(hdev);
/* Reset passive scanning to normal */
hci_update_passive_scan_sync(hdev);
hdev->scanning_paused = false;
return 0;
}
/* This function performs the HCI suspend procedures in the follow order:
*
* Restore event mask
@ -5011,10 +5072,9 @@ int hci_resume_sync(struct hci_dev *hdev)
/* Clear any event filters and restore scan state */
hci_clear_event_filter_sync(hdev);
hci_update_scan_sync(hdev);
/* Reset passive scanning to normal */
hci_update_passive_scan_sync(hdev);
/* Resume scanning */
hci_resume_scan_sync(hdev);
/* Resume monitor filters */
hci_resume_monitor_sync(hdev);

View file

@ -4529,6 +4529,23 @@ static int set_device_flags(struct sock *sk, struct hci_dev *hdev, void *data,
params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
le_addr_type(cp->addr.type));
if (params) {
DECLARE_BITMAP(flags, __HCI_CONN_NUM_FLAGS);
bitmap_from_u64(flags, current_flags);
/* Devices using RPAs can only be programmed in the
* acceptlist LL Privacy has been enable otherwise they
* cannot mark HCI_CONN_FLAG_REMOTE_WAKEUP.
*/
if (test_bit(HCI_CONN_FLAG_REMOTE_WAKEUP, flags) &&
!use_ll_privacy(hdev) &&
hci_find_irk_by_addr(hdev, &params->addr,
params->addr_type)) {
bt_dev_warn(hdev,
"Cannot set wakeable for RPA");
goto unlock;
}
bitmap_from_u64(params->flags, current_flags);
status = MGMT_STATUS_SUCCESS;
@ -4545,6 +4562,7 @@ static int set_device_flags(struct sock *sk, struct hci_dev *hdev, void *data,
}
}
unlock:
hci_dev_unlock(hdev);
done:

View file

@ -297,7 +297,7 @@ struct mgmt_pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
if (!cmd)
return NULL;
list_add(&cmd->list, &hdev->mgmt_pending);
list_add_tail(&cmd->list, &hdev->mgmt_pending);
return cmd;
}

View file

@ -574,19 +574,24 @@ static int sco_sock_connect(struct socket *sock, struct sockaddr *addr, int alen
addr->sa_family != AF_BLUETOOTH)
return -EINVAL;
if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND)
return -EBADFD;
lock_sock(sk);
if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND) {
err = -EBADFD;
goto done;
}
if (sk->sk_type != SOCK_SEQPACKET)
return -EINVAL;
if (sk->sk_type != SOCK_SEQPACKET) {
err = -EINVAL;
goto done;
}
hdev = hci_get_route(&sa->sco_bdaddr, &sco_pi(sk)->src, BDADDR_BREDR);
if (!hdev)
return -EHOSTUNREACH;
if (!hdev) {
err = -EHOSTUNREACH;
goto done;
}
hci_dev_lock(hdev);
lock_sock(sk);
/* Set destination address and psm */
bacpy(&sco_pi(sk)->dst, &sa->sco_bdaddr);
@ -885,7 +890,7 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname,
err = -EBADFD;
break;
}
if (enhanced_sco_capable(hdev) &&
if (enhanced_sync_conn_capable(hdev) &&
voice.setting == BT_VOICE_TRANSPARENT)
sco_pi(sk)->codec.id = BT_CODEC_TRANSPARENT;
hci_dev_put(hdev);