bluetooth-next pull request for net-next:

- Add 0bda:b85b for Fn-Link RTL8852BE
  - ISO: Many fixes for broadcast support
  - Mark bcm4378/bcm4387 as BROKEN_LE_CODED
  - Add support ITTIM PE50-M75C
  - Add RTW8852BE device 13d3:3570
  - Add support for QCA2066
  - Add support for Intel Misty Peak - 8087:0038
 -----BEGIN PGP SIGNATURE-----
 
 iQJNBAABCAA3FiEE7E6oRXp8w05ovYr/9JCA4xAyCykFAmU2uMkZHGx1aXoudm9u
 LmRlbnR6QGludGVsLmNvbQAKCRD0kIDjEDILKWHJD/9HYFBu6afBYi4vHF1mp6qV
 m1eGESSddZt50+xnxp/O20zL0U/xmbgabmrsY5oyxRsSapgieU2vt03tUX/RvgPK
 FIjmdXxNNYe++Uaksg2iJuySpdsPxGj/1EXEMFk8dhQ6PQYtW/w/QK4HDTcLOJMN
 pfx2NNTTcsuaoCiEPkbRybCrVvtQzcWvyKFfhEpEF4XUtU/bA1OjBJoduLolPRqJ
 p61Btt+bdgZz75tMwAGyOYJwj+uVJp4lyCdvYtUmu+lWLNqp+1a+xQWoiH1zpZ3P
 nk1r/GcumO7QSGfA9i8mnkdXGweTn6d84G5ys2JXjppTN3YuvxVy+Sr4u27POO0A
 Z3EF46BxcG6HEfTUWLBdYlMZLMUZMeSEBg4ubEVad1rEDLahZzV7DZAGyJzBgXH2
 rbHt6YTJDOm01s4+Fa92Oy4BCEdA91FCO0AhwcsV022qQ8ynOmWdz5iK7LGDcw/2
 QvWCdeCKZ11HtyVzX7SqffVDzmgNtqTtasGrhTdt/SF0pAUobgQvRTh0dx7e1BH4
 FZb4DZULu4Fs01/OyUMVNU997WDl5+B0jrrqrbh1k9vgISxisKN5CxltRSKfdYtl
 HwCmoLoXjovLH935s4AXQ/MWUk3dkgx45nfShp9QjNxfj/yMH2crwVrRUA0BBXzo
 mSGtOV/pdNyWUNVxR1R7OQ==
 =jUZj
 -----END PGP SIGNATURE-----

Merge tag 'for-net-next-2023-10-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 0bda:b85b for Fn-Link RTL8852BE
 - ISO: Many fixes for broadcast support
 - Mark bcm4378/bcm4387 as BROKEN_LE_CODED
 - Add support ITTIM PE50-M75C
 - Add RTW8852BE device 13d3:3570
 - Add support for QCA2066
 - Add support for Intel Misty Peak - 8087:0038

* tag 'for-net-next-2023-10-23' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next:
  Bluetooth: hci_sync: Fix Opcode prints in bt_dev_dbg/err
  Bluetooth: Fix double free in hci_conn_cleanup
  Bluetooth: btmtksdio: enable bluetooth wakeup in system suspend
  Bluetooth: btusb: Add 0bda:b85b for Fn-Link RTL8852BE
  Bluetooth: hci_bcm4377: Mark bcm4378/bcm4387 as BROKEN_LE_CODED
  Bluetooth: ISO: Copy BASE if service data matches EIR_BAA_SERVICE_UUID
  Bluetooth: Make handle of hci_conn be unique
  Bluetooth: btusb: Add date->evt_skb is NULL check
  Bluetooth: ISO: Fix bcast listener cleanup
  Bluetooth: msft: __hci_cmd_sync() doesn't return NULL
  Bluetooth: ISO: Match QoS adv handle with BIG handle
  Bluetooth: ISO: Allow binding a bcast listener to 0 bises
  Bluetooth: btusb: Add RTW8852BE device 13d3:3570 to device tables
  Bluetooth: qca: add support for QCA2066
  Bluetooth: ISO: Set CIS bit only for devices with CIS support
  Bluetooth: Add support for Intel Misty Peak - 8087:0038
  Bluetooth: Add support ITTIM PE50-M75C
  Bluetooth: ISO: Pass BIG encryption info through QoS
  Bluetooth: ISO: Fix BIS cleanup
====================

Link: https://lore.kernel.org/r/20231023182119.3629194-1-luiz.dentz@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski 2023-10-23 16:44:18 -07:00
commit f4dbc2bb7a
17 changed files with 392 additions and 169 deletions

View file

@ -118,6 +118,7 @@ MODULE_DEVICE_TABLE(sdio, btmtksdio_table);
#define BTMTKSDIO_FUNC_ENABLED 3
#define BTMTKSDIO_PATCH_ENABLED 4
#define BTMTKSDIO_HW_RESET_ACTIVE 5
#define BTMTKSDIO_BT_WAKE_ENABLED 6
struct mtkbtsdio_hdr {
__le16 len;
@ -554,7 +555,7 @@ static void btmtksdio_txrx_work(struct work_struct *work)
sdio_claim_host(bdev->func);
/* Disable interrupt */
sdio_writel(bdev->func, C_INT_EN_CLR, MTK_REG_CHLPCR, 0);
sdio_writel(bdev->func, C_INT_EN_CLR, MTK_REG_CHLPCR, NULL);
txrx_timeout = jiffies + 5 * HZ;
@ -576,7 +577,7 @@ static void btmtksdio_txrx_work(struct work_struct *work)
if ((int_status & FW_MAILBOX_INT) &&
bdev->data->chipid == 0x7921) {
sdio_writel(bdev->func, PH2DSM0R_DRIVER_OWN,
MTK_REG_PH2DSM0R, 0);
MTK_REG_PH2DSM0R, NULL);
}
if (int_status & FW_OWN_BACK_INT)
@ -608,7 +609,7 @@ static void btmtksdio_txrx_work(struct work_struct *work)
} while (int_status || time_is_before_jiffies(txrx_timeout));
/* Enable interrupt */
sdio_writel(bdev->func, C_INT_EN_SET, MTK_REG_CHLPCR, 0);
sdio_writel(bdev->func, C_INT_EN_SET, MTK_REG_CHLPCR, NULL);
sdio_release_host(bdev->func);
@ -620,8 +621,14 @@ static void btmtksdio_interrupt(struct sdio_func *func)
{
struct btmtksdio_dev *bdev = sdio_get_drvdata(func);
if (test_bit(BTMTKSDIO_BT_WAKE_ENABLED, &bdev->tx_state)) {
if (bdev->hdev->suspended)
pm_wakeup_event(bdev->dev, 0);
clear_bit(BTMTKSDIO_BT_WAKE_ENABLED, &bdev->tx_state);
}
/* Disable interrupt */
sdio_writel(bdev->func, C_INT_EN_CLR, MTK_REG_CHLPCR, 0);
sdio_writel(bdev->func, C_INT_EN_CLR, MTK_REG_CHLPCR, NULL);
schedule_work(&bdev->txrx_work);
}
@ -1454,6 +1461,23 @@ static int btmtksdio_runtime_suspend(struct device *dev)
return err;
}
static int btmtksdio_system_suspend(struct device *dev)
{
struct sdio_func *func = dev_to_sdio_func(dev);
struct btmtksdio_dev *bdev;
bdev = sdio_get_drvdata(func);
if (!bdev)
return 0;
if (!test_bit(BTMTKSDIO_FUNC_ENABLED, &bdev->tx_state))
return 0;
set_bit(BTMTKSDIO_BT_WAKE_ENABLED, &bdev->tx_state);
return btmtksdio_runtime_suspend(dev);
}
static int btmtksdio_runtime_resume(struct device *dev)
{
struct sdio_func *func = dev_to_sdio_func(dev);
@ -1474,8 +1498,16 @@ static int btmtksdio_runtime_resume(struct device *dev)
return err;
}
static UNIVERSAL_DEV_PM_OPS(btmtksdio_pm_ops, btmtksdio_runtime_suspend,
btmtksdio_runtime_resume, NULL);
static int btmtksdio_system_resume(struct device *dev)
{
return btmtksdio_runtime_resume(dev);
}
static const struct dev_pm_ops btmtksdio_pm_ops = {
SYSTEM_SLEEP_PM_OPS(btmtksdio_system_suspend, btmtksdio_system_resume)
RUNTIME_PM_OPS(btmtksdio_runtime_suspend, btmtksdio_runtime_resume, NULL)
};
#define BTMTKSDIO_PM_OPS (&btmtksdio_pm_ops)
#else /* CONFIG_PM */
#define BTMTKSDIO_PM_OPS NULL

View file

@ -205,6 +205,44 @@ static int qca_send_reset(struct hci_dev *hdev)
return 0;
}
static int qca_read_fw_board_id(struct hci_dev *hdev, u16 *bid)
{
u8 cmd;
struct sk_buff *skb;
struct edl_event_hdr *edl;
int err = 0;
cmd = EDL_GET_BID_REQ_CMD;
skb = __hci_cmd_sync_ev(hdev, EDL_PATCH_CMD_OPCODE, EDL_PATCH_CMD_LEN,
&cmd, 0, HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
err = PTR_ERR(skb);
bt_dev_err(hdev, "Reading QCA board ID failed (%d)", err);
return err;
}
edl = skb_pull_data(skb, sizeof(*edl));
if (!edl) {
bt_dev_err(hdev, "QCA read board ID with no header");
err = -EILSEQ;
goto out;
}
if (edl->cresp != EDL_CMD_REQ_RES_EVT ||
edl->rtype != EDL_GET_BID_REQ_CMD) {
bt_dev_err(hdev, "QCA Wrong packet: %d %d", edl->cresp, edl->rtype);
err = -EIO;
goto out;
}
*bid = (edl->data[1] << 8) + edl->data[2];
bt_dev_dbg(hdev, "%s: bid = %x", __func__, *bid);
out:
kfree_skb(skb);
return err;
}
int qca_send_pre_shutdown_cmd(struct hci_dev *hdev)
{
struct sk_buff *skb;
@ -574,6 +612,23 @@ int qca_set_bdaddr_rome(struct hci_dev *hdev, const bdaddr_t *bdaddr)
}
EXPORT_SYMBOL_GPL(qca_set_bdaddr_rome);
static void qca_generate_hsp_nvm_name(char *fwname, size_t max_size,
struct qca_btsoc_version ver, u8 rom_ver, u16 bid)
{
const char *variant;
/* hsp gf chip */
if ((le32_to_cpu(ver.soc_id) & QCA_HSP_GF_SOC_MASK) == QCA_HSP_GF_SOC_ID)
variant = "g";
else
variant = "";
if (bid == 0x0)
snprintf(fwname, max_size, "qca/hpnv%02x%s.bin", rom_ver, variant);
else
snprintf(fwname, max_size, "qca/hpnv%02x%s.%x", rom_ver, variant, bid);
}
int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
enum qca_btsoc_type soc_type, struct qca_btsoc_version ver,
const char *firmware_name)
@ -582,6 +637,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
int err;
u8 rom_ver = 0;
u32 soc_ver;
u16 boardid = 0;
bt_dev_dbg(hdev, "QCA setup on UART");
@ -615,6 +671,10 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
snprintf(config.fwname, sizeof(config.fwname),
"qca/apbtfw%02x.tlv", rom_ver);
break;
case QCA_QCA2066:
snprintf(config.fwname, sizeof(config.fwname),
"qca/hpbtfw%02x.tlv", rom_ver);
break;
case QCA_QCA6390:
snprintf(config.fwname, sizeof(config.fwname),
"qca/htbtfw%02x.tlv", rom_ver);
@ -649,6 +709,9 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
/* Give the controller some time to get ready to receive the NVM */
msleep(10);
if (soc_type == QCA_QCA2066)
qca_read_fw_board_id(hdev, &boardid);
/* Download NVM configuration */
config.type = TLV_TYPE_NVM;
if (firmware_name) {
@ -671,6 +734,10 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
snprintf(config.fwname, sizeof(config.fwname),
"qca/apnv%02x.bin", rom_ver);
break;
case QCA_QCA2066:
qca_generate_hsp_nvm_name(config.fwname,
sizeof(config.fwname), ver, rom_ver, boardid);
break;
case QCA_QCA6390:
snprintf(config.fwname, sizeof(config.fwname),
"qca/htnv%02x.bin", rom_ver);
@ -702,6 +769,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
switch (soc_type) {
case QCA_WCN3991:
case QCA_QCA2066:
case QCA_QCA6390:
case QCA_WCN6750:
case QCA_WCN6855:

View file

@ -12,6 +12,7 @@
#define EDL_PATCH_VER_REQ_CMD (0x19)
#define EDL_PATCH_TLV_REQ_CMD (0x1E)
#define EDL_GET_BUILD_INFO_CMD (0x20)
#define EDL_GET_BID_REQ_CMD (0x23)
#define EDL_NVM_ACCESS_SET_REQ_CMD (0x01)
#define EDL_PATCH_CONFIG_CMD (0x28)
#define MAX_SIZE_PER_TLV_SEGMENT (243)
@ -47,7 +48,8 @@
((le32_to_cpu(soc_id) << 16) | (le16_to_cpu(rom_ver)))
#define QCA_FW_BUILD_VER_LEN 255
#define QCA_HSP_GF_SOC_ID 0x1200
#define QCA_HSP_GF_SOC_MASK 0x0000ff00
enum qca_baudrate {
QCA_BAUDRATE_115200 = 0,
@ -146,6 +148,7 @@ enum qca_btsoc_type {
QCA_WCN3990,
QCA_WCN3998,
QCA_WCN3991,
QCA_QCA2066,
QCA_QCA6390,
QCA_WCN6750,
QCA_WCN6855,

View file

@ -477,6 +477,7 @@ static const struct usb_device_id quirks_table[] = {
{ USB_DEVICE(0x8087, 0x0033), .driver_info = BTUSB_INTEL_COMBINED },
{ USB_DEVICE(0x8087, 0x0035), .driver_info = BTUSB_INTEL_COMBINED },
{ USB_DEVICE(0x8087, 0x0036), .driver_info = BTUSB_INTEL_COMBINED },
{ USB_DEVICE(0x8087, 0x0038), .driver_info = BTUSB_INTEL_COMBINED },
{ USB_DEVICE(0x8087, 0x07da), .driver_info = BTUSB_CSR },
{ USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL_COMBINED |
BTUSB_INTEL_NO_WBS_SUPPORT |
@ -543,6 +544,10 @@ static const struct usb_device_id quirks_table[] = {
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x0bda, 0x887b), .driver_info = BTUSB_REALTEK |
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x0bda, 0xb85b), .driver_info = BTUSB_REALTEK |
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x13d3, 0x3570), .driver_info = BTUSB_REALTEK |
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x13d3, 0x3571), .driver_info = BTUSB_REALTEK |
BTUSB_WIDEBAND_SPEECH },
@ -644,6 +649,9 @@ static const struct usb_device_id quirks_table[] = {
{ USB_DEVICE(0x04ca, 0x3804), .driver_info = BTUSB_MEDIATEK |
BTUSB_WIDEBAND_SPEECH |
BTUSB_VALID_LE_STATES },
{ USB_DEVICE(0x35f5, 0x7922), .driver_info = BTUSB_MEDIATEK |
BTUSB_WIDEBAND_SPEECH |
BTUSB_VALID_LE_STATES },
/* Additional Realtek 8723AE Bluetooth devices */
{ USB_DEVICE(0x0930, 0x021d), .driver_info = BTUSB_REALTEK },
@ -2818,6 +2826,9 @@ static int btusb_mtk_hci_wmt_sync(struct hci_dev *hdev,
goto err_free_wc;
}
if (data->evt_skb == NULL)
goto err_free_wc;
/* Parse and handle the return WMT event */
wmt_evt = (struct btmtk_hci_wmt_evt *)data->evt_skb->data;
if (wmt_evt->whdr.op != hdr->op) {

View file

@ -512,6 +512,7 @@ struct bcm4377_hw {
unsigned long disable_aspm : 1;
unsigned long broken_ext_scan : 1;
unsigned long broken_mws_transport_config : 1;
unsigned long broken_le_coded : 1;
int (*send_calibration)(struct bcm4377_data *bcm4377);
int (*send_ptb)(struct bcm4377_data *bcm4377,
@ -2372,6 +2373,8 @@ static int bcm4377_probe(struct pci_dev *pdev, const struct pci_device_id *id)
set_bit(HCI_QUIRK_BROKEN_MWS_TRANSPORT_CONFIG, &hdev->quirks);
if (bcm4377->hw->broken_ext_scan)
set_bit(HCI_QUIRK_BROKEN_EXT_SCAN, &hdev->quirks);
if (bcm4377->hw->broken_le_coded)
set_bit(HCI_QUIRK_BROKEN_LE_CODED, &hdev->quirks);
pci_set_drvdata(pdev, bcm4377);
hci_set_drvdata(hdev, bcm4377);
@ -2461,6 +2464,7 @@ static const struct bcm4377_hw bcm4377_hw_variants[] = {
.bar0_core2_window2 = 0x18107000,
.has_bar0_core2_window2 = true,
.broken_mws_transport_config = true,
.broken_le_coded = true,
.send_calibration = bcm4378_send_calibration,
.send_ptb = bcm4378_send_ptb,
},
@ -2474,6 +2478,7 @@ static const struct bcm4377_hw bcm4377_hw_variants[] = {
.has_bar0_core2_window2 = true,
.clear_pciecfg_subsystem_ctrl_bit19 = true,
.broken_mws_transport_config = true,
.broken_le_coded = true,
.send_calibration = bcm4387_send_calibration,
.send_ptb = bcm4378_send_ptb,
},

View file

@ -1841,6 +1841,10 @@ static int qca_setup(struct hci_uart *hu)
set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);
switch (soc_type) {
case QCA_QCA2066:
soc_name = "qca2066";
break;
case QCA_WCN3988:
case QCA_WCN3990:
case QCA_WCN3991:
@ -2032,6 +2036,11 @@ static const struct qca_device_data qca_soc_data_wcn3998 __maybe_unused = {
.num_vregs = 4,
};
static const struct qca_device_data qca_soc_data_qca2066 __maybe_unused = {
.soc_type = QCA_QCA2066,
.num_vregs = 0,
};
static const struct qca_device_data qca_soc_data_qca6390 __maybe_unused = {
.soc_type = QCA_QCA6390,
.num_vregs = 0,
@ -2559,6 +2568,7 @@ static SIMPLE_DEV_PM_OPS(qca_pm_ops, qca_suspend, qca_resume);
#ifdef CONFIG_OF
static const struct of_device_id qca_bluetooth_of_match[] = {
{ .compatible = "qcom,qca2066-bt", .data = &qca_soc_data_qca2066},
{ .compatible = "qcom,qca6174-bt" },
{ .compatible = "qcom,qca6390-bt", .data = &qca_soc_data_qca6390},
{ .compatible = "qcom,qca9377-bt" },
@ -2576,6 +2586,7 @@ MODULE_DEVICE_TABLE(of, qca_bluetooth_of_match);
#ifdef CONFIG_ACPI
static const struct acpi_device_id qca_bluetooth_acpi_match[] = {
{ "QCOM2066", (kernel_ulong_t)&qca_soc_data_qca2066 },
{ "QCOM6390", (kernel_ulong_t)&qca_soc_data_qca6390 },
{ "DLA16390", (kernel_ulong_t)&qca_soc_data_qca6390 },
{ "DLB16390", (kernel_ulong_t)&qca_soc_data_qca6390 },

View file

@ -1,6 +1,7 @@
/*
BlueZ - Bluetooth protocol stack for Linux
Copyright (C) 2000-2001 Qualcomm Incorporated
Copyright 2023 NXP
Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
@ -673,6 +674,8 @@ enum {
#define HCI_TX_POWER_INVALID 127
#define HCI_RSSI_INVALID 127
#define HCI_SYNC_HANDLE_INVALID 0xffff
#define HCI_ROLE_MASTER 0x00
#define HCI_ROLE_SLAVE 0x01

View file

@ -350,6 +350,8 @@ struct hci_dev {
struct list_head list;
struct mutex lock;
struct ida unset_handle_ida;
const char *name;
unsigned long flags;
__u16 id;
@ -1290,31 +1292,8 @@ 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_any_dst(struct hci_dev *hdev,
__u8 handle)
{
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 != ISO_LINK)
continue;
if (handle != BT_ISO_QOS_BIG_UNSET && 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(struct hci_dev *hdev, __u8 big)
hci_conn_hash_lookup_pa_sync_big_handle(struct hci_dev *hdev, __u8 big)
{
struct hci_conn_hash *h = &hdev->conn_hash;
struct hci_conn *c;
@ -1336,6 +1315,29 @@ hci_conn_hash_lookup_pa_sync(struct hci_dev *hdev, __u8 big)
return NULL;
}
static inline struct hci_conn *
hci_conn_hash_lookup_pa_sync_handle(struct hci_dev *hdev, __u16 sync_handle)
{
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 != ISO_LINK ||
!test_bit(HCI_CONN_PA_SYNC, &c->flags))
continue;
if (c->sync_handle == sync_handle) {
rcu_read_unlock();
return c;
}
}
rcu_read_unlock();
return NULL;
}
static inline struct hci_conn *hci_conn_hash_lookup_state(struct hci_dev *hdev,
__u8 type, __u16 state)
{
@ -1377,6 +1379,26 @@ static inline void hci_conn_hash_list_state(struct hci_dev *hdev,
rcu_read_unlock();
}
static inline void hci_conn_hash_list_flag(struct hci_dev *hdev,
hci_conn_func_t func, __u8 type,
__u8 flag, void *data)
{
struct hci_conn_hash *h = &hdev->conn_hash;
struct hci_conn *c;
if (!func)
return;
rcu_read_lock();
list_for_each_entry_rcu(c, &h->list, list) {
if (c->type == type && test_bit(flag, &c->flags))
func(c, data);
}
rcu_read_unlock();
}
static inline struct hci_conn *hci_lookup_le_connect(struct hci_dev *hdev)
{
struct hci_conn_hash *h = &hdev->conn_hash;
@ -1426,7 +1448,9 @@ int hci_le_create_cis_pending(struct hci_dev *hdev);
int hci_conn_check_create_cis(struct hci_conn *conn);
struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
u8 role);
u8 role, u16 handle);
struct hci_conn *hci_conn_add_unset(struct hci_dev *hdev, int type,
bdaddr_t *dst, u8 role);
void hci_conn_del(struct hci_conn *conn);
void hci_conn_hash_flush(struct hci_dev *hdev);
void hci_conn_check_pending(struct hci_dev *hdev);

View file

@ -80,6 +80,8 @@ int hci_start_per_adv_sync(struct hci_dev *hdev, u8 instance, u8 data_len,
u8 *data, u32 flags, u16 min_interval,
u16 max_interval, u16 sync_interval);
int hci_disable_per_advertising_sync(struct hci_dev *hdev, u8 instance);
int hci_remove_advertising_sync(struct hci_dev *hdev, struct sock *sk,
u8 instance, bool force);
int hci_disable_advertising_sync(struct hci_dev *hdev);

View file

@ -109,7 +109,7 @@ struct hci_conn *phylink_add(struct hci_dev *hdev, struct amp_mgr *mgr,
struct hci_conn *hcon;
u8 role = out ? HCI_ROLE_MASTER : HCI_ROLE_SLAVE;
hcon = hci_conn_add(hdev, AMP_LINK, dst, role);
hcon = hci_conn_add(hdev, AMP_LINK, dst, role, __next_handle(mgr));
if (!hcon)
return NULL;
@ -117,7 +117,6 @@ struct hci_conn *phylink_add(struct hci_dev *hdev, struct amp_mgr *mgr,
hcon->state = BT_CONNECT;
hcon->attempt++;
hcon->handle = __next_handle(mgr);
hcon->remote_id = remote_id;
hcon->amp_mgr = amp_mgr_get(mgr);

View file

@ -153,6 +153,9 @@ static void hci_conn_cleanup(struct hci_conn *conn)
hci_conn_hash_del(hdev, conn);
if (HCI_CONN_HANDLE_UNSET(conn->handle))
ida_free(&hdev->unset_handle_ida, conn->handle);
if (conn->cleanup)
conn->cleanup(conn);
@ -169,13 +172,11 @@ static void hci_conn_cleanup(struct hci_conn *conn)
hdev->notify(hdev, HCI_NOTIFY_CONN_DEL);
}
hci_conn_del_sysfs(conn);
debugfs_remove_recursive(conn->debugfs);
hci_dev_put(hdev);
hci_conn_del_sysfs(conn);
hci_conn_put(conn);
hci_dev_put(hdev);
}
static void hci_acl_create_connection(struct hci_conn *conn)
@ -759,6 +760,7 @@ static int terminate_big_sync(struct hci_dev *hdev, void *data)
bt_dev_dbg(hdev, "big 0x%2.2x bis 0x%2.2x", d->big, d->bis);
hci_disable_per_advertising_sync(hdev, d->bis);
hci_remove_ext_adv_instance_sync(hdev, d->bis, NULL);
/* Only terminate BIG if it has been created */
@ -814,6 +816,17 @@ static int big_terminate_sync(struct hci_dev *hdev, void *data)
return 0;
}
static void find_bis(struct hci_conn *conn, void *data)
{
struct iso_list_data *d = data;
/* Ignore if BIG doesn't match */
if (d->big != conn->iso_qos.bcast.big)
return;
d->count++;
}
static int hci_le_big_terminate(struct hci_dev *hdev, u8 big, struct hci_conn *conn)
{
struct iso_list_data *d;
@ -825,10 +838,27 @@ static int hci_le_big_terminate(struct hci_dev *hdev, u8 big, struct hci_conn *c
if (!d)
return -ENOMEM;
memset(d, 0, sizeof(*d));
d->big = big;
d->sync_handle = conn->sync_handle;
d->pa_sync_term = test_and_clear_bit(HCI_CONN_PA_SYNC, &conn->flags);
d->big_sync_term = test_and_clear_bit(HCI_CONN_BIG_SYNC, &conn->flags);
if (test_and_clear_bit(HCI_CONN_PA_SYNC, &conn->flags)) {
hci_conn_hash_list_flag(hdev, find_bis, ISO_LINK,
HCI_CONN_PA_SYNC, d);
if (!d->count)
d->pa_sync_term = true;
d->count = 0;
}
if (test_and_clear_bit(HCI_CONN_BIG_SYNC, &conn->flags)) {
hci_conn_hash_list_flag(hdev, find_bis, ISO_LINK,
HCI_CONN_BIG_SYNC, d);
if (!d->count)
d->big_sync_term = true;
}
ret = hci_cmd_sync_queue(hdev, big_terminate_sync, d,
terminate_big_destroy);
@ -864,12 +894,6 @@ static void bis_cleanup(struct hci_conn *conn)
hci_le_terminate_big(hdev, conn);
} else {
bis = hci_conn_hash_lookup_big_any_dst(hdev,
conn->iso_qos.bcast.big);
if (bis)
return;
hci_le_big_terminate(hdev, conn->iso_qos.bcast.big,
conn);
}
@ -928,31 +952,18 @@ static void cis_cleanup(struct hci_conn *conn)
hci_le_remove_cig(hdev, conn->iso_qos.ucast.cig);
}
static u16 hci_conn_hash_alloc_unset(struct hci_dev *hdev)
static int hci_conn_hash_alloc_unset(struct hci_dev *hdev)
{
struct hci_conn_hash *h = &hdev->conn_hash;
struct hci_conn *c;
u16 handle = HCI_CONN_HANDLE_MAX + 1;
rcu_read_lock();
list_for_each_entry_rcu(c, &h->list, list) {
/* Find the first unused handle */
if (handle == 0xffff || c->handle != handle)
break;
handle++;
}
rcu_read_unlock();
return handle;
return ida_alloc_range(&hdev->unset_handle_ida, HCI_CONN_HANDLE_MAX + 1,
U16_MAX, GFP_ATOMIC);
}
struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
u8 role)
u8 role, u16 handle)
{
struct hci_conn *conn;
BT_DBG("%s dst %pMR", hdev->name, dst);
bt_dev_dbg(hdev, "dst %pMR handle 0x%4.4x", dst, handle);
conn = kzalloc(sizeof(*conn), GFP_KERNEL);
if (!conn)
@ -960,7 +971,7 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
bacpy(&conn->dst, dst);
bacpy(&conn->src, &hdev->bdaddr);
conn->handle = hci_conn_hash_alloc_unset(hdev);
conn->handle = handle;
conn->hdev = hdev;
conn->type = type;
conn->role = role;
@ -973,6 +984,7 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
conn->rssi = HCI_RSSI_INVALID;
conn->tx_power = HCI_TX_POWER_INVALID;
conn->max_tx_power = HCI_TX_POWER_INVALID;
conn->sync_handle = HCI_SYNC_HANDLE_INVALID;
set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
conn->disc_timeout = HCI_DISCONN_TIMEOUT;
@ -1044,6 +1056,20 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
return conn;
}
struct hci_conn *hci_conn_add_unset(struct hci_dev *hdev, int type,
bdaddr_t *dst, u8 role)
{
int handle;
bt_dev_dbg(hdev, "dst %pMR", dst);
handle = hci_conn_hash_alloc_unset(hdev);
if (unlikely(handle < 0))
return NULL;
return hci_conn_add(hdev, type, dst, role, handle);
}
static void hci_conn_cleanup_child(struct hci_conn *conn, u8 reason)
{
if (!reason)
@ -1247,6 +1273,12 @@ void hci_conn_failed(struct hci_conn *conn, u8 status)
break;
}
/* In case of BIG/PA sync failed, clear conn flags so that
* the conns will be correctly cleaned up by ISO layer
*/
test_and_clear_bit(HCI_CONN_BIG_SYNC_FAILED, &conn->flags);
test_and_clear_bit(HCI_CONN_PA_SYNC_FAILED, &conn->flags);
conn->state = BT_CLOSED;
hci_connect_cfm(conn, status);
hci_conn_del(conn);
@ -1274,6 +1306,9 @@ u8 hci_conn_set_handle(struct hci_conn *conn, u16 handle)
if (conn->abort_reason)
return conn->abort_reason;
if (HCI_CONN_HANDLE_UNSET(conn->handle))
ida_free(&hdev->unset_handle_ida, conn->handle);
conn->handle = handle;
return 0;
@ -1381,7 +1416,7 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
if (conn) {
bacpy(&conn->dst, dst);
} else {
conn = hci_conn_add(hdev, LE_LINK, dst, role);
conn = hci_conn_add_unset(hdev, LE_LINK, dst, role);
if (!conn)
return ERR_PTR(-ENOMEM);
hci_conn_hold(conn);
@ -1486,6 +1521,18 @@ static int qos_set_bis(struct hci_dev *hdev, struct bt_iso_qos *qos)
/* Allocate BIS if not set */
if (qos->bcast.bis == BT_ISO_QOS_BIS_UNSET) {
if (qos->bcast.big != BT_ISO_QOS_BIG_UNSET) {
conn = hci_conn_hash_lookup_big(hdev, qos->bcast.big);
if (conn) {
/* If the BIG handle is already matched to an advertising
* handle, do not allocate a new one.
*/
qos->bcast.bis = conn->iso_qos.bcast.bis;
return 0;
}
}
/* Find an unused adv set to advertise BIS, skip instance 0x00
* since it is reserved as general purpose set.
*/
@ -1546,7 +1593,7 @@ static struct hci_conn *hci_add_bis(struct hci_dev *hdev, bdaddr_t *dst,
memcmp(conn->le_per_adv_data, base, base_len)))
return ERR_PTR(-EADDRINUSE);
conn = hci_conn_add(hdev, ISO_LINK, dst, HCI_ROLE_MASTER);
conn = hci_conn_add_unset(hdev, ISO_LINK, dst, HCI_ROLE_MASTER);
if (!conn)
return ERR_PTR(-ENOMEM);
@ -1590,7 +1637,7 @@ struct hci_conn *hci_connect_le_scan(struct hci_dev *hdev, bdaddr_t *dst,
BT_DBG("requesting refresh of dst_addr");
conn = hci_conn_add(hdev, LE_LINK, dst, HCI_ROLE_MASTER);
conn = hci_conn_add_unset(hdev, LE_LINK, dst, HCI_ROLE_MASTER);
if (!conn)
return ERR_PTR(-ENOMEM);
@ -1638,7 +1685,7 @@ struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst,
acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
if (!acl) {
acl = hci_conn_add(hdev, ACL_LINK, dst, HCI_ROLE_MASTER);
acl = hci_conn_add_unset(hdev, ACL_LINK, dst, HCI_ROLE_MASTER);
if (!acl)
return ERR_PTR(-ENOMEM);
}
@ -1698,7 +1745,7 @@ struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst,
sco = hci_conn_hash_lookup_ba(hdev, type, dst);
if (!sco) {
sco = hci_conn_add(hdev, type, dst, HCI_ROLE_MASTER);
sco = hci_conn_add_unset(hdev, type, dst, HCI_ROLE_MASTER);
if (!sco) {
hci_conn_drop(acl);
return ERR_PTR(-ENOMEM);
@ -1890,7 +1937,7 @@ struct hci_conn *hci_bind_cis(struct hci_dev *hdev, bdaddr_t *dst,
cis = hci_conn_hash_lookup_cis(hdev, dst, dst_type, qos->ucast.cig,
qos->ucast.cis);
if (!cis) {
cis = hci_conn_add(hdev, ISO_LINK, dst, HCI_ROLE_MASTER);
cis = hci_conn_add_unset(hdev, ISO_LINK, dst, HCI_ROLE_MASTER);
if (!cis)
return ERR_PTR(-ENOMEM);
cis->cleanup = cis_cleanup;
@ -2139,7 +2186,7 @@ int hci_le_big_create_sync(struct hci_dev *hdev, struct hci_conn *hcon,
} pdu;
int err;
if (num_bis > sizeof(pdu.bis))
if (num_bis < 0x01 || num_bis > sizeof(pdu.bis))
return -EINVAL;
err = qos_set_big(hdev, qos);

View file

@ -2535,6 +2535,8 @@ struct hci_dev *hci_alloc_dev_priv(int sizeof_priv)
mutex_init(&hdev->lock);
mutex_init(&hdev->req_lock);
ida_init(&hdev->unset_handle_ida);
INIT_LIST_HEAD(&hdev->mesh_pending);
INIT_LIST_HEAD(&hdev->mgmt_pending);
INIT_LIST_HEAD(&hdev->reject_list);
@ -2789,6 +2791,7 @@ void hci_release_dev(struct hci_dev *hdev)
hci_codec_list_clear(&hdev->local_codecs);
hci_dev_unlock(hdev);
ida_destroy(&hdev->unset_handle_ida);
ida_simple_remove(&hci_index_ida, hdev->id);
kfree_skb(hdev->sent_cmd);
kfree_skb(hdev->recv_event);

View file

@ -2335,8 +2335,8 @@ static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
}
} else {
if (!conn) {
conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr,
HCI_ROLE_MASTER);
conn = hci_conn_add_unset(hdev, ACL_LINK, &cp->bdaddr,
HCI_ROLE_MASTER);
if (!conn)
bt_dev_err(hdev, "no memory for new connection");
}
@ -3151,8 +3151,8 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, void *data,
hci_bdaddr_list_lookup_with_flags(&hdev->accept_list,
&ev->bdaddr,
BDADDR_BREDR)) {
conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr,
HCI_ROLE_SLAVE);
conn = hci_conn_add_unset(hdev, ev->link_type,
&ev->bdaddr, HCI_ROLE_SLAVE);
if (!conn) {
bt_dev_err(hdev, "no memory for new conn");
goto unlock;
@ -3317,8 +3317,8 @@ static void hci_conn_request_evt(struct hci_dev *hdev, void *data,
conn = hci_conn_hash_lookup_ba(hdev, ev->link_type,
&ev->bdaddr);
if (!conn) {
conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr,
HCI_ROLE_SLAVE);
conn = hci_conn_add_unset(hdev, ev->link_type, &ev->bdaddr,
HCI_ROLE_SLAVE);
if (!conn) {
bt_dev_err(hdev, "no memory for new connection");
goto unlock;
@ -5890,7 +5890,7 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,
if (status)
goto unlock;
conn = hci_conn_add(hdev, LE_LINK, bdaddr, role);
conn = hci_conn_add_unset(hdev, LE_LINK, bdaddr, role);
if (!conn) {
bt_dev_err(hdev, "no memory for new connection");
goto unlock;
@ -5952,17 +5952,11 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,
conn->dst_type = ev_bdaddr_type(hdev, conn->dst_type, NULL);
if (handle > HCI_CONN_HANDLE_MAX) {
bt_dev_err(hdev, "Invalid handle: 0x%4.4x > 0x%4.4x", handle,
HCI_CONN_HANDLE_MAX);
status = HCI_ERROR_INVALID_PARAMETERS;
}
/* All connection failure handling is taken care of by the
* hci_conn_failed function which is triggered by the HCI
* request completion callbacks used for connecting.
*/
if (status)
if (status || hci_conn_set_handle(conn, handle))
goto unlock;
/* Drop the connection if it has been aborted */
@ -5986,7 +5980,6 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,
mgmt_device_connected(hdev, conn, NULL, 0);
conn->sec_level = BT_SECURITY_LOW;
conn->handle = handle;
conn->state = BT_CONFIG;
/* Store current advertising instance as connection advertising instance
@ -6603,7 +6596,7 @@ static void hci_le_pa_sync_estabilished_evt(struct hci_dev *hdev, void *data,
struct hci_ev_le_pa_sync_established *ev = data;
int mask = hdev->link_mode;
__u8 flags = 0;
struct hci_conn *bis;
struct hci_conn *pa_sync;
bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
@ -6620,20 +6613,19 @@ static void hci_le_pa_sync_estabilished_evt(struct hci_dev *hdev, void *data,
if (!(flags & HCI_PROTO_DEFER))
goto unlock;
/* Add connection to indicate the PA sync event */
bis = hci_conn_add(hdev, ISO_LINK, BDADDR_ANY,
HCI_ROLE_SLAVE);
if (ev->status) {
/* Add connection to indicate the failed PA sync event */
pa_sync = hci_conn_add_unset(hdev, ISO_LINK, BDADDR_ANY,
HCI_ROLE_SLAVE);
if (!bis)
goto unlock;
if (!pa_sync)
goto unlock;
if (ev->status)
set_bit(HCI_CONN_PA_SYNC_FAILED, &bis->flags);
else
set_bit(HCI_CONN_PA_SYNC, &bis->flags);
set_bit(HCI_CONN_PA_SYNC_FAILED, &pa_sync->flags);
/* Notify connection to iso layer */
hci_connect_cfm(bis, ev->status);
/* Notify iso layer */
hci_connect_cfm(pa_sync, ev->status);
}
unlock:
hci_dev_unlock(hdev);
@ -7020,12 +7012,12 @@ static void hci_le_cis_req_evt(struct hci_dev *hdev, void *data,
cis = hci_conn_hash_lookup_handle(hdev, cis_handle);
if (!cis) {
cis = hci_conn_add(hdev, ISO_LINK, &acl->dst, HCI_ROLE_SLAVE);
cis = hci_conn_add(hdev, ISO_LINK, &acl->dst, HCI_ROLE_SLAVE,
cis_handle);
if (!cis) {
hci_le_reject_cis(hdev, ev->cis_handle);
goto unlock;
}
cis->handle = cis_handle;
}
cis->iso_qos.ucast.cig = ev->cig_id;
@ -7113,7 +7105,6 @@ static void hci_le_big_sync_established_evt(struct hci_dev *hdev, void *data,
{
struct hci_evt_le_big_sync_estabilished *ev = data;
struct hci_conn *bis;
struct hci_conn *pa_sync;
int i;
bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
@ -7124,15 +7115,6 @@ static void hci_le_big_sync_established_evt(struct hci_dev *hdev, void *data,
hci_dev_lock(hdev);
if (!ev->status) {
pa_sync = hci_conn_hash_lookup_pa_sync(hdev, ev->handle);
if (pa_sync)
/* Also mark the BIG sync established event on the
* associated PA sync hcon
*/
set_bit(HCI_CONN_BIG_SYNC, &pa_sync->flags);
}
for (i = 0; i < ev->num_bis; i++) {
u16 handle = le16_to_cpu(ev->bis[i]);
__le32 interval;
@ -7140,10 +7122,9 @@ static void hci_le_big_sync_established_evt(struct hci_dev *hdev, void *data,
bis = hci_conn_hash_lookup_handle(hdev, handle);
if (!bis) {
bis = hci_conn_add(hdev, ISO_LINK, BDADDR_ANY,
HCI_ROLE_SLAVE);
HCI_ROLE_SLAVE, handle);
if (!bis)
continue;
bis->handle = handle;
}
if (ev->status != 0x42)
@ -7186,15 +7167,42 @@ static void hci_le_big_info_adv_report_evt(struct hci_dev *hdev, void *data,
struct hci_evt_le_big_info_adv_report *ev = data;
int mask = hdev->link_mode;
__u8 flags = 0;
struct hci_conn *pa_sync;
bt_dev_dbg(hdev, "sync_handle 0x%4.4x", le16_to_cpu(ev->sync_handle));
hci_dev_lock(hdev);
mask |= hci_proto_connect_ind(hdev, BDADDR_ANY, ISO_LINK, &flags);
if (!(mask & HCI_LM_ACCEPT))
if (!(mask & HCI_LM_ACCEPT)) {
hci_le_pa_term_sync(hdev, ev->sync_handle);
goto unlock;
}
if (!(flags & HCI_PROTO_DEFER))
goto unlock;
pa_sync = hci_conn_hash_lookup_pa_sync_handle
(hdev,
le16_to_cpu(ev->sync_handle));
if (pa_sync)
goto unlock;
/* Add connection to indicate the PA sync event */
pa_sync = hci_conn_add_unset(hdev, ISO_LINK, BDADDR_ANY,
HCI_ROLE_SLAVE);
if (!pa_sync)
goto unlock;
pa_sync->sync_handle = le16_to_cpu(ev->sync_handle);
set_bit(HCI_CONN_PA_SYNC, &pa_sync->flags);
/* Notify iso layer */
hci_connect_cfm(pa_sync, 0x00);
unlock:
hci_dev_unlock(hdev);
}

View file

@ -152,7 +152,7 @@ struct sk_buff *__hci_cmd_sync_sk(struct hci_dev *hdev, u16 opcode, u32 plen,
struct sk_buff *skb;
int err = 0;
bt_dev_dbg(hdev, "Opcode 0x%4x", opcode);
bt_dev_dbg(hdev, "Opcode 0x%4.4x", opcode);
hci_req_init(&req, hdev);
@ -248,7 +248,7 @@ int __hci_cmd_sync_status_sk(struct hci_dev *hdev, u16 opcode, u32 plen,
skb = __hci_cmd_sync_sk(hdev, opcode, plen, param, event, timeout, sk);
if (IS_ERR(skb)) {
if (!event)
bt_dev_err(hdev, "Opcode 0x%4x failed: %ld", opcode,
bt_dev_err(hdev, "Opcode 0x%4.4x failed: %ld", opcode,
PTR_ERR(skb));
return PTR_ERR(skb);
}
@ -1312,7 +1312,7 @@ int hci_start_ext_adv_sync(struct hci_dev *hdev, u8 instance)
return hci_enable_ext_advertising_sync(hdev, instance);
}
static int hci_disable_per_advertising_sync(struct hci_dev *hdev, u8 instance)
int hci_disable_per_advertising_sync(struct hci_dev *hdev, u8 instance)
{
struct hci_cp_le_set_per_adv_enable cp;
struct adv_info *adv = NULL;
@ -4264,12 +4264,12 @@ static int hci_le_set_host_feature_sync(struct hci_dev *hdev)
{
struct hci_cp_le_set_host_feature cp;
if (!iso_capable(hdev))
if (!cis_capable(hdev))
return 0;
memset(&cp, 0, sizeof(cp));
/* Isochronous Channels (Host Support) */
/* Connected Isochronous Channels (Host Support) */
cp.bit_number = 32;
cp.bit_value = 1;
@ -5232,6 +5232,17 @@ static int hci_disconnect_sync(struct hci_dev *hdev, struct hci_conn *conn,
if (conn->type == AMP_LINK)
return hci_disconnect_phy_link_sync(hdev, conn->handle, reason);
if (test_bit(HCI_CONN_BIG_CREATED, &conn->flags)) {
/* This is a BIS connection, hci_conn_del will
* do the necessary cleanup.
*/
hci_dev_lock(hdev);
hci_conn_failed(conn, reason);
hci_dev_unlock(hdev);
return 0;
}
memset(&cp, 0, sizeof(cp));
cp.handle = cpu_to_le16(conn->handle);
cp.reason = reason;
@ -5384,21 +5395,6 @@ int hci_abort_conn_sync(struct hci_dev *hdev, struct hci_conn *conn, u8 reason)
err = hci_reject_conn_sync(hdev, conn, reason);
break;
case BT_OPEN:
hci_dev_lock(hdev);
/* Cleanup bis or pa sync connections */
if (test_and_clear_bit(HCI_CONN_BIG_SYNC_FAILED, &conn->flags) ||
test_and_clear_bit(HCI_CONN_PA_SYNC_FAILED, &conn->flags)) {
hci_conn_failed(conn, reason);
} else if (test_bit(HCI_CONN_PA_SYNC, &conn->flags) ||
test_bit(HCI_CONN_BIG_SYNC, &conn->flags)) {
conn->state = BT_CLOSED;
hci_disconn_cfm(conn, reason);
hci_conn_del(conn);
}
hci_dev_unlock(hdev);
return 0;
case BT_BOUND:
break;
default:

View file

@ -35,7 +35,7 @@ void hci_conn_init_sysfs(struct hci_conn *conn)
{
struct hci_dev *hdev = conn->hdev;
BT_DBG("conn %p", conn);
bt_dev_dbg(hdev, "conn %p", conn);
conn->dev.type = &bt_link;
conn->dev.class = &bt_class;
@ -48,27 +48,30 @@ void hci_conn_add_sysfs(struct hci_conn *conn)
{
struct hci_dev *hdev = conn->hdev;
BT_DBG("conn %p", conn);
bt_dev_dbg(hdev, "conn %p", conn);
if (device_is_registered(&conn->dev))
return;
dev_set_name(&conn->dev, "%s:%d", hdev->name, conn->handle);
if (device_add(&conn->dev) < 0) {
if (device_add(&conn->dev) < 0)
bt_dev_err(hdev, "failed to register connection device");
return;
}
hci_dev_hold(hdev);
}
void hci_conn_del_sysfs(struct hci_conn *conn)
{
struct hci_dev *hdev = conn->hdev;
if (!device_is_registered(&conn->dev))
bt_dev_dbg(hdev, "conn %p", conn);
if (!device_is_registered(&conn->dev)) {
/* If device_add() has *not* succeeded, use *only* put_device()
* to drop the reference count.
*/
put_device(&conn->dev);
return;
}
while (1) {
struct device *dev;
@ -80,9 +83,7 @@ void hci_conn_del_sysfs(struct hci_conn *conn)
put_device(dev);
}
device_del(&conn->dev);
hci_dev_put(hdev);
device_unregister(&conn->dev);
}
static void bt_host_release(struct device *dev)

View file

@ -14,6 +14,7 @@
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
#include <net/bluetooth/iso.h>
#include "eir.h"
static const struct proto_ops iso_sock_ops;
@ -47,6 +48,7 @@ static void iso_sock_kill(struct sock *sk);
#define EIR_SERVICE_DATA_LENGTH 4
#define BASE_MAX_LENGTH (HCI_MAX_PER_AD_LENGTH - EIR_SERVICE_DATA_LENGTH)
#define EIR_BAA_SERVICE_UUID 0x1851
/* iso_pinfo flags values */
enum {
@ -77,6 +79,7 @@ static struct bt_iso_qos default_qos;
static bool check_ucast_qos(struct bt_iso_qos *qos);
static bool check_bcast_qos(struct bt_iso_qos *qos);
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);
/* ---- ISO timers ---- */
@ -789,8 +792,7 @@ 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) ||
sa->iso_bc->bc_num_bis < 0x01 || sa->iso_bc->bc_num_bis > 0x1f)
if (addr_len > sizeof(*sa) + sizeof(*sa->iso_bc))
return -EINVAL;
bacpy(&iso_pi(sk)->dst, &sa->iso_bc->bc_bdaddr);
@ -1202,7 +1204,6 @@ static int iso_sock_recvmsg(struct socket *sock, struct msghdr *msg,
test_bit(HCI_CONN_PA_SYNC, &pi->conn->hcon->flags)) {
iso_conn_big_sync(sk);
sk->sk_state = BT_LISTEN;
set_bit(BT_SK_PA_SYNC, &iso_pi(sk)->flags);
} else {
iso_conn_defer_accept(pi->conn->hcon);
sk->sk_state = BT_CONFIG;
@ -1461,6 +1462,8 @@ static int iso_sock_getsockopt(struct socket *sock, int level, int optname,
len = min_t(unsigned int, len, base_len);
if (copy_to_user(optval, base, len))
err = -EFAULT;
if (put_user(len, optlen))
err = -EFAULT;
break;
@ -1579,6 +1582,7 @@ static void iso_conn_ready(struct iso_conn *conn)
struct sock *sk = conn->sk;
struct hci_ev_le_big_sync_estabilished *ev = NULL;
struct hci_ev_le_pa_sync_established *ev2 = NULL;
struct hci_evt_le_big_info_adv_report *ev3 = NULL;
struct hci_conn *hcon;
BT_DBG("conn %p", conn);
@ -1603,14 +1607,20 @@ static void iso_conn_ready(struct iso_conn *conn)
parent = iso_get_sock_listen(&hcon->src,
&hcon->dst,
iso_match_big, ev);
} else if (test_bit(HCI_CONN_PA_SYNC, &hcon->flags) ||
test_bit(HCI_CONN_PA_SYNC_FAILED, &hcon->flags)) {
} else if (test_bit(HCI_CONN_PA_SYNC_FAILED, &hcon->flags)) {
ev2 = hci_recv_event_data(hcon->hdev,
HCI_EV_LE_PA_SYNC_ESTABLISHED);
if (ev2)
parent = iso_get_sock_listen(&hcon->src,
&hcon->dst,
iso_match_sid, ev2);
} else if (test_bit(HCI_CONN_PA_SYNC, &hcon->flags)) {
ev3 = hci_recv_event_data(hcon->hdev,
HCI_EVT_LE_BIG_INFO_ADV_REPORT);
if (ev3)
parent = iso_get_sock_listen(&hcon->src,
&hcon->dst,
iso_match_sync_handle, ev3);
}
if (!parent)
@ -1650,11 +1660,13 @@ static void iso_conn_ready(struct iso_conn *conn)
hcon->sync_handle = iso_pi(parent)->sync_handle;
}
if (ev2 && !ev2->status) {
iso_pi(sk)->sync_handle = iso_pi(parent)->sync_handle;
if (ev3) {
iso_pi(sk)->qos = iso_pi(parent)->qos;
iso_pi(sk)->qos.bcast.encryption = ev3->encryption;
hcon->iso_qos = iso_pi(sk)->qos;
iso_pi(sk)->bc_num_bis = iso_pi(parent)->bc_num_bis;
memcpy(iso_pi(sk)->bc_bis, iso_pi(parent)->bc_bis, ISO_MAX_NUM_BIS);
set_bit(BT_SK_PA_SYNC, &iso_pi(sk)->flags);
}
bacpy(&iso_pi(sk)->dst, &hcon->dst);
@ -1774,12 +1786,16 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags)
ev3 = hci_recv_event_data(hdev, HCI_EV_LE_PER_ADV_REPORT);
if (ev3) {
size_t base_len = ev3->length;
u8 *base;
sk = iso_get_sock_listen(&hdev->bdaddr, bdaddr,
iso_match_sync_handle_pa_report, ev3);
if (sk) {
memcpy(iso_pi(sk)->base, ev3->data, ev3->length);
iso_pi(sk)->base_len = ev3->length;
base = eir_get_service_data(ev3->data, ev3->length,
EIR_BAA_SERVICE_UUID, &base_len);
if (base && sk && base_len <= sizeof(iso_pi(sk)->base)) {
memcpy(iso_pi(sk)->base, base, base_len);
iso_pi(sk)->base_len = base_len;
}
} else {
sk = iso_get_sock_listen(&hdev->bdaddr, BDADDR_ANY, NULL, NULL);

View file

@ -150,10 +150,7 @@ static bool read_supported_features(struct hci_dev *hdev,
skb = __hci_cmd_sync(hdev, hdev->msft_opcode, sizeof(cp), &cp,
HCI_CMD_TIMEOUT);
if (IS_ERR_OR_NULL(skb)) {
if (!skb)
skb = ERR_PTR(-EIO);
if (IS_ERR(skb)) {
bt_dev_err(hdev, "Failed to read MSFT supported features (%ld)",
PTR_ERR(skb));
return false;
@ -353,7 +350,7 @@ static void msft_remove_addr_filters_sync(struct hci_dev *hdev, u8 handle)
skb = __hci_cmd_sync(hdev, hdev->msft_opcode, sizeof(cp), &cp,
HCI_CMD_TIMEOUT);
if (IS_ERR_OR_NULL(skb)) {
if (IS_ERR(skb)) {
kfree(address_filter);
continue;
}
@ -442,11 +439,8 @@ static int msft_remove_monitor_sync(struct hci_dev *hdev,
skb = __hci_cmd_sync(hdev, hdev->msft_opcode, sizeof(cp), &cp,
HCI_CMD_TIMEOUT);
if (IS_ERR_OR_NULL(skb)) {
if (!skb)
return -EIO;
if (IS_ERR(skb))
return PTR_ERR(skb);
}
return msft_le_cancel_monitor_advertisement_cb(hdev, hdev->msft_opcode,
monitor, skb);
@ -559,7 +553,7 @@ static int msft_add_monitor_sync(struct hci_dev *hdev,
skb = __hci_cmd_sync(hdev, hdev->msft_opcode, total_size, cp,
HCI_CMD_TIMEOUT);
if (IS_ERR_OR_NULL(skb)) {
if (IS_ERR(skb)) {
err = PTR_ERR(skb);
goto out_free;
}
@ -740,10 +734,10 @@ static int msft_cancel_address_filter_sync(struct hci_dev *hdev, void *data)
skb = __hci_cmd_sync(hdev, hdev->msft_opcode, sizeof(cp), &cp,
HCI_CMD_TIMEOUT);
if (IS_ERR_OR_NULL(skb)) {
if (IS_ERR(skb)) {
bt_dev_err(hdev, "MSFT: Failed to cancel address (%pMR) filter",
&address_filter->bdaddr);
err = -EIO;
err = PTR_ERR(skb);
goto done;
}
kfree_skb(skb);
@ -893,7 +887,7 @@ static int msft_add_address_filter_sync(struct hci_dev *hdev, void *data)
skb = __hci_cmd_sync(hdev, hdev->msft_opcode, size, cp,
HCI_CMD_TIMEOUT);
if (IS_ERR_OR_NULL(skb)) {
if (IS_ERR(skb)) {
bt_dev_err(hdev, "Failed to enable address %pMR filter",
&address_filter->bdaddr);
skb = NULL;