Commit ee7e1788 authored by Jakub Kicinski's avatar Jakub Kicinski

Merge tag 'for-net-next-2023-02-09' of...

Merge tag 'for-net-next-2023-02-09' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next

Luiz Augusto von Dentz says:

====================
pull-request: bluetooth-next

 - Add new PID/VID 0489:e0f2 for MT7921
 - Add VID:PID 13d3:3529 for Realtek RTL8821CE
 - Add CIS feature bits to controller information
 - Set Per Platform Antenna Gain(PPAG) for Intel controllers

* tag 'for-net-next-2023-02-09' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next:
  Bluetooth: btintel: Set Per Platform Antenna Gain(PPAG)
  Bluetooth: Make sure LE create conn cancel is sent when timeout
  Bluetooth: Free potentially unfreed SCO connection
  Bluetooth: hci_qca: get wakeup status from serdev device handle
  Bluetooth: L2CAP: Fix potential user-after-free
  Bluetooth: MGMT: add CIS feature bits to controller information
  Bluetooth: hci_conn: Refactor hci_bind_bis() since it always succeeds
  Bluetooth: HCI: Replace zero-length arrays with flexible-array members
  Bluetooth: qca: Fix sparse warnings
  Bluetooth: btusb: Add VID:PID 13d3:3529 for Realtek RTL8821CE
  Bluetooth: btusb: Add new PID/VID 0489:e0f2 for MT7921
  Bluetooth: Fix issue with Actions Semi ATS2851 based devices
====================

Link: https://lore.kernel.org/r/20230209234922.3756173-1-luiz.dentz@gmail.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents de428733 c585a92b
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/firmware.h> #include <linux/firmware.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/acpi.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
#include <net/bluetooth/bluetooth.h> #include <net/bluetooth/bluetooth.h>
...@@ -24,6 +25,9 @@ ...@@ -24,6 +25,9 @@
#define ECDSA_OFFSET 644 #define ECDSA_OFFSET 644
#define ECDSA_HEADER_LEN 320 #define ECDSA_HEADER_LEN 320
#define BTINTEL_PPAG_NAME "PPAG"
#define BTINTEL_PPAG_PREFIX "\\_SB_.PCI0.XHCI.RHUB"
#define CMD_WRITE_BOOT_PARAMS 0xfc0e #define CMD_WRITE_BOOT_PARAMS 0xfc0e
struct cmd_write_boot_params { struct cmd_write_boot_params {
__le32 boot_addr; __le32 boot_addr;
...@@ -1278,6 +1282,63 @@ static int btintel_read_debug_features(struct hci_dev *hdev, ...@@ -1278,6 +1282,63 @@ static int btintel_read_debug_features(struct hci_dev *hdev,
return 0; return 0;
} }
static acpi_status btintel_ppag_callback(acpi_handle handle, u32 lvl, void *data,
void **ret)
{
acpi_status status;
size_t len;
struct btintel_ppag *ppag = data;
union acpi_object *p, *elements;
struct acpi_buffer string = {ACPI_ALLOCATE_BUFFER, NULL};
struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
struct hci_dev *hdev = ppag->hdev;
status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &string);
if (ACPI_FAILURE(status)) {
bt_dev_warn(hdev, "ACPI Failure: %s", acpi_format_exception(status));
return status;
}
if (strncmp(BTINTEL_PPAG_PREFIX, string.pointer,
strlen(BTINTEL_PPAG_PREFIX))) {
kfree(string.pointer);
return AE_OK;
}
len = strlen(string.pointer);
if (strncmp((char *)string.pointer + len - 4, BTINTEL_PPAG_NAME, 4)) {
kfree(string.pointer);
return AE_OK;
}
kfree(string.pointer);
status = acpi_evaluate_object(handle, NULL, NULL, &buffer);
if (ACPI_FAILURE(status)) {
bt_dev_warn(hdev, "ACPI Failure: %s", acpi_format_exception(status));
return status;
}
p = buffer.pointer;
ppag = (struct btintel_ppag *)data;
if (p->type != ACPI_TYPE_PACKAGE || p->package.count != 2) {
kfree(buffer.pointer);
bt_dev_warn(hdev, "Invalid object type: %d or package count: %d",
p->type, p->package.count);
return AE_ERROR;
}
elements = p->package.elements;
/* PPAG table is located at element[1] */
p = &elements[1];
ppag->domain = (u32)p->package.elements[0].integer.value;
ppag->mode = (u32)p->package.elements[1].integer.value;
kfree(buffer.pointer);
return AE_CTRL_TERMINATE;
}
static int btintel_set_debug_features(struct hci_dev *hdev, static int btintel_set_debug_features(struct hci_dev *hdev,
const struct intel_debug_features *features) const struct intel_debug_features *features)
{ {
...@@ -2251,6 +2312,58 @@ static int btintel_configure_offload(struct hci_dev *hdev) ...@@ -2251,6 +2312,58 @@ static int btintel_configure_offload(struct hci_dev *hdev)
return err; return err;
} }
static void btintel_set_ppag(struct hci_dev *hdev, struct intel_version_tlv *ver)
{
acpi_status status;
struct btintel_ppag ppag;
struct sk_buff *skb;
struct btintel_loc_aware_reg ppag_cmd;
/* PPAG is not supported if CRF is HrP2, Jfp2, JfP1 */
switch (ver->cnvr_top & 0xFFF) {
case 0x504: /* Hrp2 */
case 0x202: /* Jfp2 */
case 0x201: /* Jfp1 */
return;
}
memset(&ppag, 0, sizeof(ppag));
ppag.hdev = hdev;
status = acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
ACPI_UINT32_MAX, NULL,
btintel_ppag_callback, &ppag, NULL);
if (ACPI_FAILURE(status)) {
/* Do not log warning message if ACPI entry is not found */
if (status == AE_NOT_FOUND)
return;
bt_dev_warn(hdev, "PPAG: ACPI Failure: %s", acpi_format_exception(status));
return;
}
if (ppag.domain != 0x12) {
bt_dev_warn(hdev, "PPAG-BT Domain disabled");
return;
}
/* PPAG mode, BIT0 = 0 Disabled, BIT0 = 1 Enabled */
if (!(ppag.mode & BIT(0))) {
bt_dev_dbg(hdev, "PPAG disabled");
return;
}
ppag_cmd.mcc = cpu_to_le32(0);
ppag_cmd.sel = cpu_to_le32(0); /* 0 - Enable , 1 - Disable, 2 - Testing mode */
ppag_cmd.delta = cpu_to_le32(0);
skb = __hci_cmd_sync(hdev, 0xfe19, sizeof(ppag_cmd), &ppag_cmd, HCI_CMD_TIMEOUT);
if (IS_ERR(skb)) {
bt_dev_warn(hdev, "Failed to send PPAG Enable (%ld)", PTR_ERR(skb));
return;
}
kfree_skb(skb);
}
static int btintel_bootloader_setup_tlv(struct hci_dev *hdev, static int btintel_bootloader_setup_tlv(struct hci_dev *hdev,
struct intel_version_tlv *ver) struct intel_version_tlv *ver)
{ {
...@@ -2297,6 +2410,9 @@ static int btintel_bootloader_setup_tlv(struct hci_dev *hdev, ...@@ -2297,6 +2410,9 @@ static int btintel_bootloader_setup_tlv(struct hci_dev *hdev,
hci_dev_clear_flag(hdev, HCI_QUALITY_REPORT); hci_dev_clear_flag(hdev, HCI_QUALITY_REPORT);
/* Set PPAG feature */
btintel_set_ppag(hdev, ver);
/* Read the Intel version information after loading the FW */ /* Read the Intel version information after loading the FW */
err = btintel_read_version_tlv(hdev, &new_ver); err = btintel_read_version_tlv(hdev, &new_ver);
if (err) if (err)
......
...@@ -137,6 +137,19 @@ struct intel_offload_use_cases { ...@@ -137,6 +137,19 @@ struct intel_offload_use_cases {
__u8 preset[8]; __u8 preset[8];
} __packed; } __packed;
/* structure to store the PPAG data read from ACPI table */
struct btintel_ppag {
u32 domain;
u32 mode;
struct hci_dev *hdev;
};
struct btintel_loc_aware_reg {
__le32 mcc;
__le32 sel;
__le32 delta;
} __packed;
#define INTEL_HW_PLATFORM(cnvx_bt) ((u8)(((cnvx_bt) & 0x0000ff00) >> 8)) #define INTEL_HW_PLATFORM(cnvx_bt) ((u8)(((cnvx_bt) & 0x0000ff00) >> 8))
#define INTEL_HW_VARIANT(cnvx_bt) ((u8)(((cnvx_bt) & 0x003f0000) >> 16)) #define INTEL_HW_VARIANT(cnvx_bt) ((u8)(((cnvx_bt) & 0x003f0000) >> 16))
#define INTEL_CNVX_TOP_TYPE(cnvx_top) ((cnvx_top) & 0x00000fff) #define INTEL_CNVX_TOP_TYPE(cnvx_top) ((cnvx_top) & 0x00000fff)
......
...@@ -64,6 +64,7 @@ static struct usb_driver btusb_driver; ...@@ -64,6 +64,7 @@ static struct usb_driver btusb_driver;
#define BTUSB_INTEL_BROKEN_SHUTDOWN_LED BIT(24) #define BTUSB_INTEL_BROKEN_SHUTDOWN_LED BIT(24)
#define BTUSB_INTEL_BROKEN_INITIAL_NCMD BIT(25) #define BTUSB_INTEL_BROKEN_INITIAL_NCMD BIT(25)
#define BTUSB_INTEL_NO_WBS_SUPPORT BIT(26) #define BTUSB_INTEL_NO_WBS_SUPPORT BIT(26)
#define BTUSB_ACTIONS_SEMI BIT(27)
static const struct usb_device_id btusb_table[] = { static const struct usb_device_id btusb_table[] = {
/* Generic Bluetooth USB device */ /* Generic Bluetooth USB device */
...@@ -492,6 +493,10 @@ static const struct usb_device_id blacklist_table[] = { ...@@ -492,6 +493,10 @@ static const struct usb_device_id blacklist_table[] = {
{ USB_VENDOR_AND_INTERFACE_INFO(0x8087, 0xe0, 0x01, 0x01), { USB_VENDOR_AND_INTERFACE_INFO(0x8087, 0xe0, 0x01, 0x01),
.driver_info = BTUSB_IGNORE }, .driver_info = BTUSB_IGNORE },
/* Realtek 8821CE Bluetooth devices */
{ USB_DEVICE(0x13d3, 0x3529), .driver_info = BTUSB_REALTEK |
BTUSB_WIDEBAND_SPEECH },
/* Realtek 8822CE Bluetooth devices */ /* Realtek 8822CE Bluetooth devices */
{ USB_DEVICE(0x0bda, 0xb00c), .driver_info = BTUSB_REALTEK | { USB_DEVICE(0x0bda, 0xb00c), .driver_info = BTUSB_REALTEK |
BTUSB_WIDEBAND_SPEECH }, BTUSB_WIDEBAND_SPEECH },
...@@ -566,6 +571,9 @@ static const struct usb_device_id blacklist_table[] = { ...@@ -566,6 +571,9 @@ static const struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x0489, 0xe0e0), .driver_info = BTUSB_MEDIATEK | { USB_DEVICE(0x0489, 0xe0e0), .driver_info = BTUSB_MEDIATEK |
BTUSB_WIDEBAND_SPEECH | BTUSB_WIDEBAND_SPEECH |
BTUSB_VALID_LE_STATES }, BTUSB_VALID_LE_STATES },
{ USB_DEVICE(0x0489, 0xe0f2), .driver_info = BTUSB_MEDIATEK |
BTUSB_WIDEBAND_SPEECH |
BTUSB_VALID_LE_STATES },
{ USB_DEVICE(0x04ca, 0x3802), .driver_info = BTUSB_MEDIATEK | { USB_DEVICE(0x04ca, 0x3802), .driver_info = BTUSB_MEDIATEK |
BTUSB_WIDEBAND_SPEECH | BTUSB_WIDEBAND_SPEECH |
BTUSB_VALID_LE_STATES }, BTUSB_VALID_LE_STATES },
...@@ -677,6 +685,9 @@ static const struct usb_device_id blacklist_table[] = { ...@@ -677,6 +685,9 @@ static const struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x0cb5, 0xc547), .driver_info = BTUSB_REALTEK | { USB_DEVICE(0x0cb5, 0xc547), .driver_info = BTUSB_REALTEK |
BTUSB_WIDEBAND_SPEECH }, BTUSB_WIDEBAND_SPEECH },
/* Actions Semiconductor ATS2851 based devices */
{ USB_DEVICE(0x10d7, 0xb012), .driver_info = BTUSB_ACTIONS_SEMI },
/* Silicon Wave based devices */ /* Silicon Wave based devices */
{ USB_DEVICE(0x0c10, 0x0000), .driver_info = BTUSB_SWAVE }, { USB_DEVICE(0x0c10, 0x0000), .driver_info = BTUSB_SWAVE },
...@@ -4098,6 +4109,11 @@ static int btusb_probe(struct usb_interface *intf, ...@@ -4098,6 +4109,11 @@ static int btusb_probe(struct usb_interface *intf,
set_bit(BTUSB_USE_ALT3_FOR_WBS, &data->flags); set_bit(BTUSB_USE_ALT3_FOR_WBS, &data->flags);
} }
if (id->driver_info & BTUSB_ACTIONS_SEMI) {
/* Support is advertised, but not implemented */
set_bit(HCI_QUIRK_BROKEN_ERR_DATA_REPORTING, &hdev->quirks);
}
if (!reset) if (!reset)
set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks); set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
......
...@@ -128,13 +128,13 @@ struct qca_memdump_event_hdr { ...@@ -128,13 +128,13 @@ struct qca_memdump_event_hdr {
__u8 evt; __u8 evt;
__u8 plen; __u8 plen;
__u16 opcode; __u16 opcode;
__u16 seq_no; __le16 seq_no;
__u8 reserved; __u8 reserved;
} __packed; } __packed;
struct qca_dump_size { struct qca_dump_size {
u32 dump_size; __le32 dump_size;
} __packed; } __packed;
struct qca_data { struct qca_data {
...@@ -1588,10 +1588,11 @@ static bool qca_wakeup(struct hci_dev *hdev) ...@@ -1588,10 +1588,11 @@ static bool qca_wakeup(struct hci_dev *hdev)
struct hci_uart *hu = hci_get_drvdata(hdev); struct hci_uart *hu = hci_get_drvdata(hdev);
bool wakeup; bool wakeup;
/* UART driver handles the interrupt from BT SoC.So we need to use /* BT SoC attached through the serial bus is handled by the serdev driver.
* device handle of UART driver to get the status of device may wakeup. * So we need to use the device handle of the serdev driver to get the
* status of device may wakeup.
*/ */
wakeup = device_may_wakeup(hu->serdev->ctrl->dev.parent); wakeup = device_may_wakeup(&hu->serdev->ctrl->dev);
bt_dev_dbg(hu->hdev, "wakeup status : %d", wakeup); bt_dev_dbg(hu->hdev, "wakeup status : %d", wakeup);
return wakeup; return wakeup;
......
...@@ -2156,7 +2156,7 @@ struct hci_cp_le_big_create_sync { ...@@ -2156,7 +2156,7 @@ struct hci_cp_le_big_create_sync {
__u8 mse; __u8 mse;
__le16 timeout; __le16 timeout;
__u8 num_bis; __u8 num_bis;
__u8 bis[0]; __u8 bis[];
} __packed; } __packed;
#define HCI_OP_LE_BIG_TERM_SYNC 0x206c #define HCI_OP_LE_BIG_TERM_SYNC 0x206c
...@@ -2174,7 +2174,7 @@ struct hci_cp_le_setup_iso_path { ...@@ -2174,7 +2174,7 @@ struct hci_cp_le_setup_iso_path {
__le16 codec_vid; __le16 codec_vid;
__u8 delay[3]; __u8 delay[3];
__u8 codec_cfg_len; __u8 codec_cfg_len;
__u8 codec_cfg[0]; __u8 codec_cfg[];
} __packed; } __packed;
struct hci_rp_le_setup_iso_path { struct hci_rp_le_setup_iso_path {
......
...@@ -109,6 +109,8 @@ struct mgmt_rp_read_index_list { ...@@ -109,6 +109,8 @@ struct mgmt_rp_read_index_list {
#define MGMT_SETTING_STATIC_ADDRESS 0x00008000 #define MGMT_SETTING_STATIC_ADDRESS 0x00008000
#define MGMT_SETTING_PHY_CONFIGURATION 0x00010000 #define MGMT_SETTING_PHY_CONFIGURATION 0x00010000
#define MGMT_SETTING_WIDEBAND_SPEECH 0x00020000 #define MGMT_SETTING_WIDEBAND_SPEECH 0x00020000
#define MGMT_SETTING_CIS_CENTRAL 0x00040000
#define MGMT_SETTING_CIS_PERIPHERAL 0x00080000
#define MGMT_OP_READ_INFO 0x0004 #define MGMT_OP_READ_INFO 0x0004
#define MGMT_READ_INFO_SIZE 0 #define MGMT_READ_INFO_SIZE 0
......
...@@ -1061,8 +1061,15 @@ int hci_conn_del(struct hci_conn *conn) ...@@ -1061,8 +1061,15 @@ int hci_conn_del(struct hci_conn *conn)
if (conn->type == ACL_LINK) { if (conn->type == ACL_LINK) {
struct hci_conn *sco = conn->link; struct hci_conn *sco = conn->link;
if (sco) if (sco) {
sco->link = NULL; sco->link = NULL;
/* Due to race, SCO connection might be not established
* yet at this point. Delete it now, otherwise it is
* possible for it to be stuck and can't be deleted.
*/
if (sco->handle == HCI_CONN_HANDLE_UNSET)
hci_conn_del(sco);
}
/* Unacked frames */ /* Unacked frames */
hdev->acl_cnt += conn->sent; hdev->acl_cnt += conn->sent;
...@@ -1243,6 +1250,8 @@ static void create_le_conn_complete(struct hci_dev *hdev, void *data, int err) ...@@ -1243,6 +1250,8 @@ static void create_le_conn_complete(struct hci_dev *hdev, void *data, int err)
if (conn != hci_lookup_le_connect(hdev)) if (conn != hci_lookup_le_connect(hdev))
goto done; goto done;
/* Flush to make sure we send create conn cancel command if needed */
flush_delayed_work(&conn->le_conn_timeout);
hci_conn_failed(conn, bt_status(err)); hci_conn_failed(conn, bt_status(err));
done: done:
...@@ -1981,16 +1990,14 @@ static void hci_iso_qos_setup(struct hci_dev *hdev, struct hci_conn *conn, ...@@ -1981,16 +1990,14 @@ static void hci_iso_qos_setup(struct hci_dev *hdev, struct hci_conn *conn,
qos->latency = conn->le_conn_latency; qos->latency = conn->le_conn_latency;
} }
static struct hci_conn *hci_bind_bis(struct hci_conn *conn, static void hci_bind_bis(struct hci_conn *conn,
struct bt_iso_qos *qos) struct bt_iso_qos *qos)
{ {
/* Update LINK PHYs according to QoS preference */ /* Update LINK PHYs according to QoS preference */
conn->le_tx_phy = qos->out.phy; conn->le_tx_phy = qos->out.phy;
conn->le_tx_phy = qos->out.phy; conn->le_tx_phy = qos->out.phy;
conn->iso_qos = *qos; conn->iso_qos = *qos;
conn->state = BT_BOUND; conn->state = BT_BOUND;
return conn;
} }
static int create_big_sync(struct hci_dev *hdev, void *data) static int create_big_sync(struct hci_dev *hdev, void *data)
...@@ -2119,11 +2126,7 @@ struct hci_conn *hci_connect_bis(struct hci_dev *hdev, bdaddr_t *dst, ...@@ -2119,11 +2126,7 @@ struct hci_conn *hci_connect_bis(struct hci_dev *hdev, bdaddr_t *dst,
if (IS_ERR(conn)) if (IS_ERR(conn))
return conn; return conn;
conn = hci_bind_bis(conn, qos); hci_bind_bis(conn, qos);
if (!conn) {
hci_conn_drop(conn);
return ERR_PTR(-ENOMEM);
}
/* Add Basic Announcement into Peridic Adv Data if BASE is set */ /* Add Basic Announcement into Peridic Adv Data if BASE is set */
if (base_len && base) { if (base_len && base) {
......
...@@ -2683,14 +2683,6 @@ int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len) ...@@ -2683,14 +2683,6 @@ int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
if (IS_ERR(skb)) if (IS_ERR(skb))
return PTR_ERR(skb); return PTR_ERR(skb);
/* Channel lock is released before requesting new skb and then
* reacquired thus we need to recheck channel state.
*/
if (chan->state != BT_CONNECTED) {
kfree_skb(skb);
return -ENOTCONN;
}
l2cap_do_send(chan, skb); l2cap_do_send(chan, skb);
return len; return len;
} }
...@@ -2735,14 +2727,6 @@ int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len) ...@@ -2735,14 +2727,6 @@ int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
if (IS_ERR(skb)) if (IS_ERR(skb))
return PTR_ERR(skb); return PTR_ERR(skb);
/* Channel lock is released before requesting new skb and then
* reacquired thus we need to recheck channel state.
*/
if (chan->state != BT_CONNECTED) {
kfree_skb(skb);
return -ENOTCONN;
}
l2cap_do_send(chan, skb); l2cap_do_send(chan, skb);
err = len; err = len;
break; break;
...@@ -2763,14 +2747,6 @@ int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len) ...@@ -2763,14 +2747,6 @@ int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
*/ */
err = l2cap_segment_sdu(chan, &seg_queue, msg, len); err = l2cap_segment_sdu(chan, &seg_queue, msg, len);
/* The channel could have been closed while segmenting,
* check that it is still connected.
*/
if (chan->state != BT_CONNECTED) {
__skb_queue_purge(&seg_queue);
err = -ENOTCONN;
}
if (err) if (err)
break; break;
......
...@@ -1624,6 +1624,14 @@ static struct sk_buff *l2cap_sock_alloc_skb_cb(struct l2cap_chan *chan, ...@@ -1624,6 +1624,14 @@ static struct sk_buff *l2cap_sock_alloc_skb_cb(struct l2cap_chan *chan,
if (!skb) if (!skb)
return ERR_PTR(err); return ERR_PTR(err);
/* Channel lock is released before requesting new skb and then
* reacquired thus we need to recheck channel state.
*/
if (chan->state != BT_CONNECTED) {
kfree_skb(skb);
return ERR_PTR(-ENOTCONN);
}
skb->priority = sk->sk_priority; skb->priority = sk->sk_priority;
bt_cb(skb)->l2cap.chan = chan; bt_cb(skb)->l2cap.chan = chan;
......
...@@ -859,6 +859,12 @@ static u32 get_supported_settings(struct hci_dev *hdev) ...@@ -859,6 +859,12 @@ static u32 get_supported_settings(struct hci_dev *hdev)
hdev->set_bdaddr) hdev->set_bdaddr)
settings |= MGMT_SETTING_CONFIGURATION; settings |= MGMT_SETTING_CONFIGURATION;
if (cis_central_capable(hdev))
settings |= MGMT_SETTING_CIS_CENTRAL;
if (cis_peripheral_capable(hdev))
settings |= MGMT_SETTING_CIS_PERIPHERAL;
settings |= MGMT_SETTING_PHY_CONFIGURATION; settings |= MGMT_SETTING_PHY_CONFIGURATION;
return settings; return settings;
...@@ -932,6 +938,12 @@ static u32 get_current_settings(struct hci_dev *hdev) ...@@ -932,6 +938,12 @@ static u32 get_current_settings(struct hci_dev *hdev)
if (hci_dev_test_flag(hdev, HCI_WIDEBAND_SPEECH_ENABLED)) if (hci_dev_test_flag(hdev, HCI_WIDEBAND_SPEECH_ENABLED))
settings |= MGMT_SETTING_WIDEBAND_SPEECH; settings |= MGMT_SETTING_WIDEBAND_SPEECH;
if (cis_central_capable(hdev))
settings |= MGMT_SETTING_CIS_CENTRAL;
if (cis_peripheral_capable(hdev))
settings |= MGMT_SETTING_CIS_PERIPHERAL;
return settings; return settings;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment