Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next
Johan Hedberg says: ==================== pull request: bluetooth-next 2020-05-13 Here's a second attempt at a bluetooth-next pull request which supercedes the one dated 2020-05-09. This should have the issues discovered by Jakub fixed. - Add support for Intel Typhoon Peak device (8087:0032) - Add device tree bindings for Realtek RTL8723BS device - Add device tree bindings for Qualcomm QCA9377 device - Add support for experimental features configuration through mgmt - Add driver hook to prevent wake from suspend - Add support for waiting for L2CAP disconnection response - Multiple fixes & cleanups to the btbcm driver - Add support for LE scatternet topology for selected devices - A few other smaller fixes & cleanups Please let me know if there are any issues pulling. Thanks. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
6cd35888a0
@ -10,6 +10,7 @@ device the slave device is attached to.
|
||||
Required properties:
|
||||
- compatible: should contain one of the following:
|
||||
* "qcom,qca6174-bt"
|
||||
* "qcom,qca9377-bt"
|
||||
* "qcom,wcn3990-bt"
|
||||
* "qcom,wcn3991-bt"
|
||||
* "qcom,wcn3998-bt"
|
||||
@ -21,6 +22,10 @@ Optional properties for compatible string qcom,qca6174-bt:
|
||||
- clocks: clock provided to the controller (SUSCLK_32KHZ)
|
||||
- firmware-name: specify the name of nvm firmware to load
|
||||
|
||||
Optional properties for compatible string qcom,qca9377-bt:
|
||||
|
||||
- max-speed: see Documentation/devicetree/bindings/serial/serial.yaml
|
||||
|
||||
Required properties for compatible string qcom,wcn399x-bt:
|
||||
|
||||
- vddio-supply: VDD_IO supply regulator handle.
|
||||
|
54
Documentation/devicetree/bindings/net/realtek-bluetooth.yaml
Normal file
54
Documentation/devicetree/bindings/net/realtek-bluetooth.yaml
Normal file
@ -0,0 +1,54 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/net/realtek-bluetooth.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: RTL8723BS/RTL8723CS/RTL8822CS Bluetooth Device Tree Bindings
|
||||
|
||||
maintainers:
|
||||
- Vasily Khoruzhick <anarsoul@gmail.com>
|
||||
- Alistair Francis <alistair@alistair23.me>
|
||||
|
||||
description:
|
||||
RTL8723CS/RTL8723CS/RTL8822CS is WiFi + BT chip. WiFi part is connected over
|
||||
SDIO, while BT is connected over serial. It speaks H5 protocol with few
|
||||
extra commands to upload firmware and change module speed.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- const: "realtek,rtl8723bs-bt"
|
||||
- const: "realtek,rtl8723cs-bt"
|
||||
- const: "realtek,rtl8822cs-bt"
|
||||
|
||||
device-wake-gpios:
|
||||
maxItems: 1
|
||||
description: GPIO specifier, used to wakeup the BT module
|
||||
|
||||
enable-gpios:
|
||||
maxItems: 1
|
||||
description: GPIO specifier, used to enable the BT module
|
||||
|
||||
host-wake-gpios:
|
||||
maxItems: 1
|
||||
description: GPIO specifier, used to wakeup the host processor
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
uart1 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&uart1_pins>, <&uart1_rts_cts_pins>;
|
||||
uart-has-rtscts = <1>;
|
||||
|
||||
bluetooth {
|
||||
compatible = "realtek,rtl8723bs-bt";
|
||||
device-wake-gpios = <&r_pio 0 5 GPIO_ACTIVE_HIGH>; /* PL5 */
|
||||
host-wakeup-gpios = <&r_pio 0 6 GPIO_ACTIVE_HIGH>; /* PL6 */
|
||||
};
|
||||
};
|
@ -27,6 +27,11 @@
|
||||
#define BDADDR_BCM4345C5 (&(bdaddr_t) {{0xac, 0x1f, 0x00, 0xc5, 0x45, 0x43}})
|
||||
#define BDADDR_BCM43341B (&(bdaddr_t) {{0xac, 0x1f, 0x00, 0x1b, 0x34, 0x43}})
|
||||
|
||||
#define BCM_FW_NAME_LEN 64
|
||||
#define BCM_FW_NAME_COUNT_MAX 2
|
||||
/* For kmalloc-ing the fw-name array instead of putting it on the stack */
|
||||
typedef char bcm_fw_name[BCM_FW_NAME_LEN];
|
||||
|
||||
int btbcm_check_bdaddr(struct hci_dev *hdev)
|
||||
{
|
||||
struct hci_rp_read_bd_addr *bda;
|
||||
@ -358,6 +363,13 @@ static int btbcm_read_info(struct hci_dev *hdev)
|
||||
bt_dev_info(hdev, "BCM: features 0x%2.2x", skb->data[1]);
|
||||
kfree_skb(skb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int btbcm_print_local_name(struct hci_dev *hdev)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
|
||||
/* Read Local Name */
|
||||
skb = btbcm_read_local_name(hdev);
|
||||
if (IS_ERR(skb))
|
||||
@ -380,6 +392,7 @@ static const struct bcm_subver_table bcm_uart_subver_table[] = {
|
||||
{ 0x410e, "BCM43341B0" }, /* 002.001.014 */
|
||||
{ 0x4204, "BCM2076B1" }, /* 002.002.004 */
|
||||
{ 0x4406, "BCM4324B3" }, /* 002.004.006 */
|
||||
{ 0x4606, "BCM4324B5" }, /* 002.006.006 */
|
||||
{ 0x6109, "BCM4335C0" }, /* 003.001.009 */
|
||||
{ 0x610c, "BCM4354" }, /* 003.001.012 */
|
||||
{ 0x2122, "BCM4343A0" }, /* 001.001.034 */
|
||||
@ -395,6 +408,7 @@ static const struct bcm_subver_table bcm_uart_subver_table[] = {
|
||||
};
|
||||
|
||||
static const struct bcm_subver_table bcm_usb_subver_table[] = {
|
||||
{ 0x2105, "BCM20703A1" }, /* 001.001.005 */
|
||||
{ 0x210b, "BCM43142A0" }, /* 001.001.011 */
|
||||
{ 0x2112, "BCM4314A0" }, /* 001.001.018 */
|
||||
{ 0x2118, "BCM20702A0" }, /* 001.001.024 */
|
||||
@ -408,14 +422,17 @@ static const struct bcm_subver_table bcm_usb_subver_table[] = {
|
||||
{ }
|
||||
};
|
||||
|
||||
int btbcm_initialize(struct hci_dev *hdev, char *fw_name, size_t len,
|
||||
bool reinit)
|
||||
int btbcm_initialize(struct hci_dev *hdev, bool *fw_load_done)
|
||||
{
|
||||
u16 subver, rev, pid, vid;
|
||||
const char *hw_name = "BCM";
|
||||
struct sk_buff *skb;
|
||||
struct hci_rp_read_local_version *ver;
|
||||
const struct bcm_subver_table *bcm_subver_table;
|
||||
const char *hw_name = NULL;
|
||||
char postfix[16] = "";
|
||||
int fw_name_count = 0;
|
||||
bcm_fw_name *fw_name;
|
||||
const struct firmware *fw;
|
||||
int i, err;
|
||||
|
||||
/* Reset */
|
||||
@ -434,15 +451,14 @@ int btbcm_initialize(struct hci_dev *hdev, char *fw_name, size_t len,
|
||||
kfree_skb(skb);
|
||||
|
||||
/* Read controller information */
|
||||
if (!reinit) {
|
||||
if (!(*fw_load_done)) {
|
||||
err = btbcm_read_info(hdev);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Upper nibble of rev should be between 0 and 3? */
|
||||
if (((rev & 0xf000) >> 12) > 3)
|
||||
return 0;
|
||||
err = btbcm_print_local_name(hdev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
bcm_subver_table = (hdev->bus == HCI_USB) ? bcm_usb_subver_table :
|
||||
bcm_uart_subver_table;
|
||||
@ -454,6 +470,13 @@ int btbcm_initialize(struct hci_dev *hdev, char *fw_name, size_t len,
|
||||
}
|
||||
}
|
||||
|
||||
bt_dev_info(hdev, "%s (%3.3u.%3.3u.%3.3u) build %4.4u",
|
||||
hw_name ? hw_name : "BCM", (subver & 0xe000) >> 13,
|
||||
(subver & 0x1f00) >> 8, (subver & 0x00ff), rev & 0x0fff);
|
||||
|
||||
if (*fw_load_done)
|
||||
return 0;
|
||||
|
||||
if (hdev->bus == HCI_USB) {
|
||||
/* Read USB Product Info */
|
||||
skb = btbcm_read_usb_product(hdev);
|
||||
@ -464,85 +487,81 @@ int btbcm_initialize(struct hci_dev *hdev, char *fw_name, size_t len,
|
||||
pid = get_unaligned_le16(skb->data + 3);
|
||||
kfree_skb(skb);
|
||||
|
||||
snprintf(fw_name, len, "brcm/%s-%4.4x-%4.4x.hcd",
|
||||
hw_name, vid, pid);
|
||||
} else {
|
||||
snprintf(fw_name, len, "brcm/%s.hcd", hw_name);
|
||||
snprintf(postfix, sizeof(postfix), "-%4.4x-%4.4x", vid, pid);
|
||||
}
|
||||
|
||||
bt_dev_info(hdev, "%s (%3.3u.%3.3u.%3.3u) build %4.4u",
|
||||
hw_name, (subver & 0xe000) >> 13,
|
||||
(subver & 0x1f00) >> 8, (subver & 0x00ff), rev & 0x0fff);
|
||||
fw_name = kmalloc(BCM_FW_NAME_COUNT_MAX * BCM_FW_NAME_LEN, GFP_KERNEL);
|
||||
if (!fw_name)
|
||||
return -ENOMEM;
|
||||
|
||||
if (hw_name) {
|
||||
snprintf(fw_name[fw_name_count], BCM_FW_NAME_LEN,
|
||||
"brcm/%s%s.hcd", hw_name, postfix);
|
||||
fw_name_count++;
|
||||
}
|
||||
|
||||
snprintf(fw_name[fw_name_count], BCM_FW_NAME_LEN,
|
||||
"brcm/BCM%s.hcd", postfix);
|
||||
fw_name_count++;
|
||||
|
||||
for (i = 0; i < fw_name_count; i++) {
|
||||
err = firmware_request_nowarn(&fw, fw_name[i], &hdev->dev);
|
||||
if (err == 0) {
|
||||
bt_dev_info(hdev, "%s '%s' Patch",
|
||||
hw_name ? hw_name : "BCM", fw_name[i]);
|
||||
*fw_load_done = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (*fw_load_done) {
|
||||
err = btbcm_patchram(hdev, fw);
|
||||
if (err)
|
||||
bt_dev_info(hdev, "BCM: Patch failed (%d)", err);
|
||||
|
||||
release_firmware(fw);
|
||||
} else {
|
||||
bt_dev_err(hdev, "BCM: firmware Patch file not found, tried:");
|
||||
for (i = 0; i < fw_name_count; i++)
|
||||
bt_dev_err(hdev, "BCM: '%s'", fw_name[i]);
|
||||
}
|
||||
|
||||
kfree(fw_name);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(btbcm_initialize);
|
||||
|
||||
int btbcm_finalize(struct hci_dev *hdev)
|
||||
int btbcm_finalize(struct hci_dev *hdev, bool *fw_load_done)
|
||||
{
|
||||
char fw_name[64];
|
||||
int err;
|
||||
|
||||
/* Re-initialize */
|
||||
err = btbcm_initialize(hdev, fw_name, sizeof(fw_name), true);
|
||||
if (err)
|
||||
return err;
|
||||
/* Re-initialize if necessary */
|
||||
if (*fw_load_done) {
|
||||
err = btbcm_initialize(hdev, fw_load_done);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
btbcm_check_bdaddr(hdev);
|
||||
|
||||
set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks);
|
||||
|
||||
/* Some devices ship with the controller default address.
|
||||
* Allow the bootloader to set a valid address through the
|
||||
* device tree.
|
||||
*/
|
||||
set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(btbcm_finalize);
|
||||
|
||||
int btbcm_setup_patchram(struct hci_dev *hdev)
|
||||
{
|
||||
char fw_name[64];
|
||||
const struct firmware *fw;
|
||||
struct sk_buff *skb;
|
||||
bool fw_load_done = false;
|
||||
int err;
|
||||
|
||||
/* Initialize */
|
||||
err = btbcm_initialize(hdev, fw_name, sizeof(fw_name), false);
|
||||
err = btbcm_initialize(hdev, &fw_load_done);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = request_firmware(&fw, fw_name, &hdev->dev);
|
||||
if (err < 0) {
|
||||
bt_dev_info(hdev, "BCM: Patch %s not found", fw_name);
|
||||
goto done;
|
||||
}
|
||||
|
||||
btbcm_patchram(hdev, fw);
|
||||
|
||||
release_firmware(fw);
|
||||
|
||||
/* Re-initialize */
|
||||
err = btbcm_initialize(hdev, fw_name, sizeof(fw_name), true);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Read Local Name */
|
||||
skb = btbcm_read_local_name(hdev);
|
||||
if (IS_ERR(skb))
|
||||
return PTR_ERR(skb);
|
||||
|
||||
bt_dev_info(hdev, "%s", (char *)(skb->data + 1));
|
||||
kfree_skb(skb);
|
||||
|
||||
done:
|
||||
btbcm_check_bdaddr(hdev);
|
||||
|
||||
set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks);
|
||||
|
||||
return 0;
|
||||
/* Re-initialize after loading Patch */
|
||||
return btbcm_finalize(hdev, &fw_load_done);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(btbcm_setup_patchram);
|
||||
|
||||
|
@ -62,9 +62,8 @@ int btbcm_write_pcm_int_params(struct hci_dev *hdev,
|
||||
int btbcm_setup_patchram(struct hci_dev *hdev);
|
||||
int btbcm_setup_apple(struct hci_dev *hdev);
|
||||
|
||||
int btbcm_initialize(struct hci_dev *hdev, char *fw_name, size_t len,
|
||||
bool reinit);
|
||||
int btbcm_finalize(struct hci_dev *hdev);
|
||||
int btbcm_initialize(struct hci_dev *hdev, bool *fw_load_done);
|
||||
int btbcm_finalize(struct hci_dev *hdev, bool *fw_load_done);
|
||||
|
||||
#else
|
||||
|
||||
@ -105,13 +104,12 @@ static inline int btbcm_setup_apple(struct hci_dev *hdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int btbcm_initialize(struct hci_dev *hdev, char *fw_name,
|
||||
size_t len, bool reinit)
|
||||
static inline int btbcm_initialize(struct hci_dev *hdev, bool *fw_load_done)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int btbcm_finalize(struct hci_dev *hdev)
|
||||
static inline int btbcm_finalize(struct hci_dev *hdev, bool *fw_load_done)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -58,6 +58,7 @@ static struct usb_driver btusb_driver;
|
||||
#define BTUSB_CW6622 0x100000
|
||||
#define BTUSB_MEDIATEK 0x200000
|
||||
#define BTUSB_WIDEBAND_SPEECH 0x400000
|
||||
#define BTUSB_VALID_LE_STATES 0x800000
|
||||
|
||||
static const struct usb_device_id btusb_table[] = {
|
||||
/* Generic Bluetooth USB device */
|
||||
@ -335,11 +336,14 @@ static const struct usb_device_id blacklist_table[] = {
|
||||
|
||||
/* Intel Bluetooth devices */
|
||||
{ USB_DEVICE(0x8087, 0x0025), .driver_info = BTUSB_INTEL_NEW |
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
{ USB_DEVICE(0x8087, 0x0026), .driver_info = BTUSB_INTEL_NEW |
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x8087, 0x0029), .driver_info = BTUSB_INTEL_NEW |
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x8087, 0x0032), .driver_info = BTUSB_INTEL_NEW |
|
||||
BTUSB_WIDEBAND_SPEECH},
|
||||
{ USB_DEVICE(0x8087, 0x07da), .driver_info = BTUSB_CSR },
|
||||
{ USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL },
|
||||
{ USB_DEVICE(0x8087, 0x0a2a), .driver_info = BTUSB_INTEL },
|
||||
@ -348,7 +352,8 @@ static const struct usb_device_id blacklist_table[] = {
|
||||
{ USB_DEVICE(0x8087, 0x0aa7), .driver_info = BTUSB_INTEL |
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x8087, 0x0aaa), .driver_info = BTUSB_INTEL_NEW |
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
|
||||
/* Other Intel Bluetooth devices */
|
||||
{ USB_VENDOR_AND_INTERFACE_INFO(0x8087, 0xe0, 0x01, 0x01),
|
||||
@ -3695,6 +3700,13 @@ static void btusb_check_needs_reset_resume(struct usb_interface *intf)
|
||||
interface_to_usbdev(intf)->quirks |= USB_QUIRK_RESET_RESUME;
|
||||
}
|
||||
|
||||
static bool btusb_prevent_wake(struct hci_dev *hdev)
|
||||
{
|
||||
struct btusb_data *data = hci_get_drvdata(hdev);
|
||||
|
||||
return !device_may_wakeup(&data->udev->dev);
|
||||
}
|
||||
|
||||
static int btusb_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
@ -3828,6 +3840,7 @@ static int btusb_probe(struct usb_interface *intf,
|
||||
hdev->flush = btusb_flush;
|
||||
hdev->send = btusb_send_frame;
|
||||
hdev->notify = btusb_notify;
|
||||
hdev->prevent_wake = btusb_prevent_wake;
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
err = btusb_config_oob_wake(hdev);
|
||||
@ -3972,6 +3985,9 @@ static int btusb_probe(struct usb_interface *intf,
|
||||
if (id->driver_info & BTUSB_WIDEBAND_SPEECH)
|
||||
set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks);
|
||||
|
||||
if (id->driver_info & BTUSB_VALID_LE_STATES)
|
||||
set_bit(HCI_QUIRK_VALID_LE_STATES, &hdev->quirks);
|
||||
|
||||
if (id->driver_info & BTUSB_DIGIANSWER) {
|
||||
data->cmdreq_type = USB_TYPE_VENDOR;
|
||||
set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
|
||||
|
@ -553,8 +553,7 @@ static int bcm_flush(struct hci_uart *hu)
|
||||
static int bcm_setup(struct hci_uart *hu)
|
||||
{
|
||||
struct bcm_data *bcm = hu->priv;
|
||||
char fw_name[64];
|
||||
const struct firmware *fw;
|
||||
bool fw_load_done = false;
|
||||
unsigned int speed;
|
||||
int err;
|
||||
|
||||
@ -563,21 +562,12 @@ static int bcm_setup(struct hci_uart *hu)
|
||||
hu->hdev->set_diag = bcm_set_diag;
|
||||
hu->hdev->set_bdaddr = btbcm_set_bdaddr;
|
||||
|
||||
err = btbcm_initialize(hu->hdev, fw_name, sizeof(fw_name), false);
|
||||
err = btbcm_initialize(hu->hdev, &fw_load_done);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = request_firmware(&fw, fw_name, &hu->hdev->dev);
|
||||
if (err < 0) {
|
||||
bt_dev_info(hu->hdev, "BCM: Patch %s not found", fw_name);
|
||||
if (!fw_load_done)
|
||||
return 0;
|
||||
}
|
||||
|
||||
err = btbcm_patchram(hu->hdev, fw);
|
||||
if (err) {
|
||||
bt_dev_info(hu->hdev, "BCM: Patch failed (%d)", err);
|
||||
goto finalize;
|
||||
}
|
||||
|
||||
/* Init speed if any */
|
||||
if (hu->init_speed)
|
||||
@ -616,13 +606,16 @@ static int bcm_setup(struct hci_uart *hu)
|
||||
btbcm_write_pcm_int_params(hu->hdev, ¶ms);
|
||||
}
|
||||
|
||||
finalize:
|
||||
release_firmware(fw);
|
||||
|
||||
err = btbcm_finalize(hu->hdev);
|
||||
err = btbcm_finalize(hu->hdev, &fw_load_done);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Some devices ship with the controller default address.
|
||||
* Allow the bootloader to set a valid address through the
|
||||
* device tree.
|
||||
*/
|
||||
set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hu->hdev->quirks);
|
||||
|
||||
if (!bcm_request_irq(bcm))
|
||||
err = bcm_setup_sleep(hu);
|
||||
|
||||
|
@ -1018,6 +1018,8 @@ static const struct of_device_id rtl_bluetooth_of_match[] = {
|
||||
#ifdef CONFIG_BT_HCIUART_RTL
|
||||
{ .compatible = "realtek,rtl8822cs-bt",
|
||||
.data = (const void *)&rtl_vnd },
|
||||
{ .compatible = "realtek,rtl8723bs-bt",
|
||||
.data = (const void *)&rtl_vnd },
|
||||
#endif
|
||||
{ },
|
||||
};
|
||||
|
@ -597,10 +597,12 @@ static int qca_open(struct hci_uart *hu)
|
||||
|
||||
if (hu->serdev) {
|
||||
qcadev = serdev_device_get_drvdata(hu->serdev);
|
||||
if (qca_is_wcn399x(qcadev->btsoc_type)) {
|
||||
|
||||
if (qca_is_wcn399x(qcadev->btsoc_type))
|
||||
hu->init_speed = qcadev->init_speed;
|
||||
|
||||
if (qcadev->oper_speed)
|
||||
hu->oper_speed = qcadev->oper_speed;
|
||||
}
|
||||
}
|
||||
|
||||
timer_setup(&qca->wake_retrans_timer, hci_ibs_wake_retrans_timeout, 0);
|
||||
@ -1871,6 +1873,11 @@ static int qca_serdev_probe(struct serdev_device *serdev)
|
||||
serdev_device_set_drvdata(serdev, qcadev);
|
||||
device_property_read_string(&serdev->dev, "firmware-name",
|
||||
&qcadev->firmware_name);
|
||||
device_property_read_u32(&serdev->dev, "max-speed",
|
||||
&qcadev->oper_speed);
|
||||
if (!qcadev->oper_speed)
|
||||
BT_DBG("UART will pick default operating speed");
|
||||
|
||||
if (data && qca_is_wcn399x(data->soc_type)) {
|
||||
qcadev->btsoc_type = data->soc_type;
|
||||
qcadev->bt_power = devm_kzalloc(&serdev->dev,
|
||||
@ -1895,11 +1902,6 @@ static int qca_serdev_probe(struct serdev_device *serdev)
|
||||
return PTR_ERR(qcadev->susclk);
|
||||
}
|
||||
|
||||
device_property_read_u32(&serdev->dev, "max-speed",
|
||||
&qcadev->oper_speed);
|
||||
if (!qcadev->oper_speed)
|
||||
BT_DBG("UART will pick default operating speed");
|
||||
|
||||
err = hci_uart_register_device(&qcadev->serdev_hu, &qca_proto);
|
||||
if (err) {
|
||||
BT_ERR("wcn3990 serdev registration failed");
|
||||
@ -2058,6 +2060,7 @@ static SIMPLE_DEV_PM_OPS(qca_pm_ops, qca_suspend, qca_resume);
|
||||
static const struct of_device_id qca_bluetooth_of_match[] = {
|
||||
{ .compatible = "qcom,qca6174-bt" },
|
||||
{ .compatible = "qcom,qca6390-bt", .data = &qca_soc_data_qca6390},
|
||||
{ .compatible = "qcom,qca9377-bt" },
|
||||
{ .compatible = "qcom,wcn3990-bt", .data = &qca_soc_data_wcn3990},
|
||||
{ .compatible = "qcom,wcn3991-bt", .data = &qca_soc_data_wcn3991},
|
||||
{ .compatible = "qcom,wcn3998-bt", .data = &qca_soc_data_wcn3998},
|
||||
|
@ -21,8 +21,6 @@
|
||||
|
||||
#include "hci_uart.h"
|
||||
|
||||
static struct serdev_device_ops hci_serdev_client_ops;
|
||||
|
||||
static inline void hci_uart_tx_complete(struct hci_uart *hu, int pkt_type)
|
||||
{
|
||||
struct hci_dev *hdev = hu->hdev;
|
||||
@ -260,7 +258,7 @@ static int hci_uart_receive_buf(struct serdev_device *serdev, const u8 *data,
|
||||
return count;
|
||||
}
|
||||
|
||||
static struct serdev_device_ops hci_serdev_client_ops = {
|
||||
static const struct serdev_device_ops hci_serdev_client_ops = {
|
||||
.receive_buf = hci_uart_receive_buf,
|
||||
.write_wakeup = hci_uart_write_wakeup,
|
||||
};
|
||||
|
@ -153,6 +153,12 @@ __printf(1, 2)
|
||||
void bt_warn(const char *fmt, ...);
|
||||
__printf(1, 2)
|
||||
void bt_err(const char *fmt, ...);
|
||||
#if IS_ENABLED(CONFIG_BT_FEATURE_DEBUG)
|
||||
void bt_dbg_set(bool enable);
|
||||
bool bt_dbg_get(void);
|
||||
__printf(1, 2)
|
||||
void bt_dbg(const char *fmt, ...);
|
||||
#endif
|
||||
__printf(1, 2)
|
||||
void bt_warn_ratelimited(const char *fmt, ...);
|
||||
__printf(1, 2)
|
||||
@ -161,7 +167,12 @@ void bt_err_ratelimited(const char *fmt, ...);
|
||||
#define BT_INFO(fmt, ...) bt_info(fmt "\n", ##__VA_ARGS__)
|
||||
#define BT_WARN(fmt, ...) bt_warn(fmt "\n", ##__VA_ARGS__)
|
||||
#define BT_ERR(fmt, ...) bt_err(fmt "\n", ##__VA_ARGS__)
|
||||
|
||||
#if IS_ENABLED(CONFIG_BT_FEATURE_DEBUG)
|
||||
#define BT_DBG(fmt, ...) bt_dbg(fmt "\n", ##__VA_ARGS__)
|
||||
#else
|
||||
#define BT_DBG(fmt, ...) pr_debug(fmt "\n", ##__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#define bt_dev_info(hdev, fmt, ...) \
|
||||
BT_INFO("%s: " fmt, (hdev)->name, ##__VA_ARGS__)
|
||||
|
@ -218,6 +218,15 @@ enum {
|
||||
* This quirk must be set before hci_register_dev is called.
|
||||
*/
|
||||
HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED,
|
||||
|
||||
/* When this quirk is set, the controller has validated that
|
||||
* LE states reported through the HCI_LE_READ_SUPPORTED_STATES are
|
||||
* valid. This mechanism is necessary as many controllers have
|
||||
* been seen has having trouble initiating a connectable
|
||||
* advertisement despite the state combination being reported as
|
||||
* supported.
|
||||
*/
|
||||
HCI_QUIRK_VALID_LE_STATES,
|
||||
};
|
||||
|
||||
/* HCI device flags */
|
||||
@ -249,6 +258,7 @@ enum {
|
||||
HCI_MGMT_DEV_CLASS_EVENTS,
|
||||
HCI_MGMT_LOCAL_NAME_EVENTS,
|
||||
HCI_MGMT_OOB_DATA_EVENTS,
|
||||
HCI_MGMT_EXP_FEATURE_EVENTS,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -110,7 +110,7 @@ enum suspend_tasks {
|
||||
enum suspended_state {
|
||||
BT_RUNNING = 0,
|
||||
BT_SUSPEND_DISCONNECT,
|
||||
BT_SUSPEND_COMPLETE,
|
||||
BT_SUSPEND_CONFIGURE_WAKE,
|
||||
};
|
||||
|
||||
struct hci_conn_hash {
|
||||
@ -503,6 +503,7 @@ struct hci_dev {
|
||||
int (*set_diag)(struct hci_dev *hdev, bool enable);
|
||||
int (*set_bdaddr)(struct hci_dev *hdev, const bdaddr_t *bdaddr);
|
||||
void (*cmd_timeout)(struct hci_dev *hdev);
|
||||
bool (*prevent_wake)(struct hci_dev *hdev);
|
||||
};
|
||||
|
||||
#define HCI_PHY_HANDLE(handle) (handle & 0xff)
|
||||
@ -1554,6 +1555,7 @@ void hci_sock_dev_event(struct hci_dev *hdev, int event);
|
||||
#define HCI_MGMT_NO_HDEV BIT(1)
|
||||
#define HCI_MGMT_UNTRUSTED BIT(2)
|
||||
#define HCI_MGMT_UNCONFIGURED BIT(3)
|
||||
#define HCI_MGMT_HDEV_OPTIONAL BIT(4)
|
||||
|
||||
struct hci_mgmt_handler {
|
||||
int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
|
||||
|
@ -70,14 +70,14 @@ struct mgmt_rp_read_version {
|
||||
struct mgmt_rp_read_commands {
|
||||
__le16 num_commands;
|
||||
__le16 num_events;
|
||||
__le16 opcodes[0];
|
||||
__le16 opcodes[];
|
||||
} __packed;
|
||||
|
||||
#define MGMT_OP_READ_INDEX_LIST 0x0003
|
||||
#define MGMT_READ_INDEX_LIST_SIZE 0
|
||||
struct mgmt_rp_read_index_list {
|
||||
__le16 num_controllers;
|
||||
__le16 index[0];
|
||||
__le16 index[];
|
||||
} __packed;
|
||||
|
||||
/* Reserve one extra byte for names in management messages so that they
|
||||
@ -183,7 +183,7 @@ struct mgmt_link_key_info {
|
||||
struct mgmt_cp_load_link_keys {
|
||||
__u8 debug_keys;
|
||||
__le16 key_count;
|
||||
struct mgmt_link_key_info keys[0];
|
||||
struct mgmt_link_key_info keys[];
|
||||
} __packed;
|
||||
#define MGMT_LOAD_LINK_KEYS_SIZE 3
|
||||
|
||||
@ -206,7 +206,7 @@ struct mgmt_ltk_info {
|
||||
#define MGMT_OP_LOAD_LONG_TERM_KEYS 0x0013
|
||||
struct mgmt_cp_load_long_term_keys {
|
||||
__le16 key_count;
|
||||
struct mgmt_ltk_info keys[0];
|
||||
struct mgmt_ltk_info keys[];
|
||||
} __packed;
|
||||
#define MGMT_LOAD_LONG_TERM_KEYS_SIZE 2
|
||||
|
||||
@ -223,7 +223,7 @@ struct mgmt_rp_disconnect {
|
||||
#define MGMT_GET_CONNECTIONS_SIZE 0
|
||||
struct mgmt_rp_get_connections {
|
||||
__le16 conn_count;
|
||||
struct mgmt_addr_info addr[0];
|
||||
struct mgmt_addr_info addr[];
|
||||
} __packed;
|
||||
|
||||
#define MGMT_OP_PIN_CODE_REPLY 0x0016
|
||||
@ -413,7 +413,7 @@ struct mgmt_irk_info {
|
||||
#define MGMT_OP_LOAD_IRKS 0x0030
|
||||
struct mgmt_cp_load_irks {
|
||||
__le16 irk_count;
|
||||
struct mgmt_irk_info irks[0];
|
||||
struct mgmt_irk_info irks[];
|
||||
} __packed;
|
||||
#define MGMT_LOAD_IRKS_SIZE 2
|
||||
|
||||
@ -465,7 +465,7 @@ struct mgmt_conn_param {
|
||||
#define MGMT_OP_LOAD_CONN_PARAM 0x0035
|
||||
struct mgmt_cp_load_conn_param {
|
||||
__le16 param_count;
|
||||
struct mgmt_conn_param params[0];
|
||||
struct mgmt_conn_param params[];
|
||||
} __packed;
|
||||
#define MGMT_LOAD_CONN_PARAM_SIZE 2
|
||||
|
||||
@ -473,7 +473,7 @@ struct mgmt_cp_load_conn_param {
|
||||
#define MGMT_READ_UNCONF_INDEX_LIST_SIZE 0
|
||||
struct mgmt_rp_read_unconf_index_list {
|
||||
__le16 num_controllers;
|
||||
__le16 index[0];
|
||||
__le16 index[];
|
||||
} __packed;
|
||||
|
||||
#define MGMT_OPTION_EXTERNAL_CONFIG 0x00000001
|
||||
@ -504,7 +504,7 @@ struct mgmt_cp_start_service_discovery {
|
||||
__u8 type;
|
||||
__s8 rssi;
|
||||
__le16 uuid_count;
|
||||
__u8 uuids[0][16];
|
||||
__u8 uuids[][16];
|
||||
} __packed;
|
||||
#define MGMT_START_SERVICE_DISCOVERY_SIZE 4
|
||||
|
||||
@ -516,7 +516,7 @@ struct mgmt_cp_read_local_oob_ext_data {
|
||||
struct mgmt_rp_read_local_oob_ext_data {
|
||||
__u8 type;
|
||||
__le16 eir_len;
|
||||
__u8 eir[0];
|
||||
__u8 eir[];
|
||||
} __packed;
|
||||
|
||||
#define MGMT_OP_READ_EXT_INDEX_LIST 0x003C
|
||||
@ -527,7 +527,7 @@ struct mgmt_rp_read_ext_index_list {
|
||||
__le16 index;
|
||||
__u8 type;
|
||||
__u8 bus;
|
||||
} entry[0];
|
||||
} entry[];
|
||||
} __packed;
|
||||
|
||||
#define MGMT_OP_READ_ADV_FEATURES 0x0003D
|
||||
@ -538,7 +538,7 @@ struct mgmt_rp_read_adv_features {
|
||||
__u8 max_scan_rsp_len;
|
||||
__u8 max_instances;
|
||||
__u8 num_instances;
|
||||
__u8 instance[0];
|
||||
__u8 instance[];
|
||||
} __packed;
|
||||
|
||||
#define MGMT_OP_ADD_ADVERTISING 0x003E
|
||||
@ -549,7 +549,7 @@ struct mgmt_cp_add_advertising {
|
||||
__le16 timeout;
|
||||
__u8 adv_data_len;
|
||||
__u8 scan_rsp_len;
|
||||
__u8 data[0];
|
||||
__u8 data[];
|
||||
} __packed;
|
||||
#define MGMT_ADD_ADVERTISING_SIZE 11
|
||||
struct mgmt_rp_add_advertising {
|
||||
@ -603,7 +603,7 @@ struct mgmt_rp_read_ext_info {
|
||||
__le32 supported_settings;
|
||||
__le32 current_settings;
|
||||
__le16 eir_len;
|
||||
__u8 eir[0];
|
||||
__u8 eir[];
|
||||
} __packed;
|
||||
|
||||
#define MGMT_OP_SET_APPEARANCE 0x0043
|
||||
@ -668,7 +668,7 @@ struct mgmt_blocked_key_info {
|
||||
|
||||
struct mgmt_cp_set_blocked_keys {
|
||||
__le16 key_count;
|
||||
struct mgmt_blocked_key_info keys[0];
|
||||
struct mgmt_blocked_key_info keys[];
|
||||
} __packed;
|
||||
#define MGMT_OP_SET_BLOCKED_KEYS_SIZE 2
|
||||
|
||||
@ -678,14 +678,35 @@ struct mgmt_cp_set_blocked_keys {
|
||||
#define MGMT_READ_SECURITY_INFO_SIZE 0
|
||||
struct mgmt_rp_read_security_info {
|
||||
__le16 sec_len;
|
||||
__u8 sec[0];
|
||||
__u8 sec[];
|
||||
} __packed;
|
||||
|
||||
#define MGMT_OP_READ_EXP_FEATURES_INFO 0x0049
|
||||
#define MGMT_READ_EXP_FEATURES_INFO_SIZE 0
|
||||
struct mgmt_rp_read_exp_features_info {
|
||||
__le16 feature_count;
|
||||
struct {
|
||||
__u8 uuid[16];
|
||||
__le32 flags;
|
||||
} features[];
|
||||
} __packed;
|
||||
|
||||
#define MGMT_OP_SET_EXP_FEATURE 0x004a
|
||||
struct mgmt_cp_set_exp_feature {
|
||||
__u8 uuid[16];
|
||||
__u8 param[];
|
||||
} __packed;
|
||||
#define MGMT_SET_EXP_FEATURE_SIZE 16
|
||||
struct mgmt_rp_set_exp_feature {
|
||||
__u8 uuid[16];
|
||||
__le32 flags;
|
||||
} __packed;
|
||||
|
||||
#define MGMT_EV_CMD_COMPLETE 0x0001
|
||||
struct mgmt_ev_cmd_complete {
|
||||
__le16 opcode;
|
||||
__u8 status;
|
||||
__u8 data[0];
|
||||
__u8 data[];
|
||||
} __packed;
|
||||
|
||||
#define MGMT_EV_CMD_STATUS 0x0002
|
||||
@ -733,7 +754,7 @@ struct mgmt_ev_device_connected {
|
||||
struct mgmt_addr_info addr;
|
||||
__le32 flags;
|
||||
__le16 eir_len;
|
||||
__u8 eir[0];
|
||||
__u8 eir[];
|
||||
} __packed;
|
||||
|
||||
#define MGMT_DEV_DISCONN_UNKNOWN 0x00
|
||||
@ -788,7 +809,7 @@ struct mgmt_ev_device_found {
|
||||
__s8 rssi;
|
||||
__le32 flags;
|
||||
__le16 eir_len;
|
||||
__u8 eir[0];
|
||||
__u8 eir[];
|
||||
} __packed;
|
||||
|
||||
#define MGMT_EV_DISCOVERING 0x0013
|
||||
@ -883,7 +904,7 @@ struct mgmt_ev_ext_index {
|
||||
struct mgmt_ev_local_oob_data_updated {
|
||||
__u8 type;
|
||||
__le16 eir_len;
|
||||
__u8 eir[0];
|
||||
__u8 eir[];
|
||||
} __packed;
|
||||
|
||||
#define MGMT_EV_ADVERTISING_ADDED 0x0023
|
||||
@ -899,10 +920,16 @@ struct mgmt_ev_advertising_removed {
|
||||
#define MGMT_EV_EXT_INFO_CHANGED 0x0025
|
||||
struct mgmt_ev_ext_info_changed {
|
||||
__le16 eir_len;
|
||||
__u8 eir[0];
|
||||
__u8 eir[];
|
||||
} __packed;
|
||||
|
||||
#define MGMT_EV_PHY_CONFIGURATION_CHANGED 0x0026
|
||||
struct mgmt_ev_phy_configuration_changed {
|
||||
__le32 selected_phys;
|
||||
} __packed;
|
||||
|
||||
#define MGMT_EV_EXP_FEATURE_CHANGED 0x0027
|
||||
struct mgmt_ev_exp_feature_changed {
|
||||
__u8 uuid[16];
|
||||
__le32 flags;
|
||||
} __packed;
|
||||
|
@ -135,4 +135,11 @@ config BT_SELFTEST_SMP
|
||||
Run test cases for SMP cryptographic functionality, including both
|
||||
legacy SMP as well as the Secure Connections features.
|
||||
|
||||
config BT_FEATURE_DEBUG
|
||||
bool "Enable runtime option for debugging statements"
|
||||
depends on BT && !DYNAMIC_DEBUG
|
||||
help
|
||||
This provides an option to enable/disable debugging statements
|
||||
at runtime via the experimental features interface.
|
||||
|
||||
source "drivers/bluetooth/Kconfig"
|
||||
|
@ -3350,10 +3350,12 @@ static int hci_suspend_notifier(struct notifier_block *nb, unsigned long action,
|
||||
*/
|
||||
ret = hci_change_suspend_state(hdev, BT_SUSPEND_DISCONNECT);
|
||||
|
||||
/* Only configure whitelist if disconnect succeeded */
|
||||
if (!ret)
|
||||
/* Only configure whitelist if disconnect succeeded and wake
|
||||
* isn't being prevented.
|
||||
*/
|
||||
if (!ret && !(hdev->prevent_wake && hdev->prevent_wake(hdev)))
|
||||
ret = hci_change_suspend_state(hdev,
|
||||
BT_SUSPEND_COMPLETE);
|
||||
BT_SUSPEND_CONFIGURE_WAKE);
|
||||
} else if (action == PM_POST_SUSPEND) {
|
||||
ret = hci_change_suspend_state(hdev, BT_RUNNING);
|
||||
}
|
||||
|
@ -42,12 +42,27 @@
|
||||
|
||||
/* Handle HCI Event packets */
|
||||
|
||||
static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb,
|
||||
u8 *new_status)
|
||||
{
|
||||
__u8 status = *((__u8 *) skb->data);
|
||||
|
||||
BT_DBG("%s status 0x%2.2x", hdev->name, status);
|
||||
|
||||
/* It is possible that we receive Inquiry Complete event right
|
||||
* before we receive Inquiry Cancel Command Complete event, in
|
||||
* which case the latter event should have status of Command
|
||||
* Disallowed (0x0c). This should not be treated as error, since
|
||||
* we actually achieve what Inquiry Cancel wants to achieve,
|
||||
* which is to end the last Inquiry session.
|
||||
*/
|
||||
if (status == 0x0c && !test_bit(HCI_INQUIRY, &hdev->flags)) {
|
||||
bt_dev_warn(hdev, "Ignoring error of Inquiry Cancel command");
|
||||
status = 0x00;
|
||||
}
|
||||
|
||||
*new_status = status;
|
||||
|
||||
if (status)
|
||||
return;
|
||||
|
||||
@ -3233,7 +3248,7 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb,
|
||||
|
||||
switch (*opcode) {
|
||||
case HCI_OP_INQUIRY_CANCEL:
|
||||
hci_cc_inquiry_cancel(hdev, skb);
|
||||
hci_cc_inquiry_cancel(hdev, skb, status);
|
||||
break;
|
||||
|
||||
case HCI_OP_PERIODIC_INQ:
|
||||
@ -5288,7 +5303,9 @@ static struct hci_conn *check_pending_le_conn(struct hci_dev *hdev,
|
||||
/* Most controller will fail if we try to create new connections
|
||||
* while we have an existing one in slave role.
|
||||
*/
|
||||
if (hdev->conn_hash.le_num_slave > 0)
|
||||
if (hdev->conn_hash.le_num_slave > 0 &&
|
||||
(!test_bit(HCI_QUIRK_VALID_LE_STATES, &hdev->quirks) ||
|
||||
!(hdev->le_states[3] & 0x10)))
|
||||
return NULL;
|
||||
|
||||
/* If we're not connectable only connect devices that we have in
|
||||
|
@ -35,7 +35,7 @@
|
||||
#define HCI_REQ_CANCELED 2
|
||||
|
||||
#define LE_SUSPEND_SCAN_WINDOW 0x0012
|
||||
#define LE_SUSPEND_SCAN_INTERVAL 0x0060
|
||||
#define LE_SUSPEND_SCAN_INTERVAL 0x0400
|
||||
|
||||
void hci_req_init(struct hci_request *req, struct hci_dev *hdev)
|
||||
{
|
||||
@ -890,7 +890,7 @@ void hci_req_add_le_passive_scan(struct hci_request *req)
|
||||
struct hci_dev *hdev = req->hdev;
|
||||
u8 own_addr_type;
|
||||
u8 filter_policy;
|
||||
u8 window, interval;
|
||||
u16 window, interval;
|
||||
|
||||
if (hdev->scanning_paused) {
|
||||
bt_dev_dbg(hdev, "Scanning is paused for suspend");
|
||||
@ -1090,7 +1090,7 @@ void hci_req_prepare_suspend(struct hci_dev *hdev, enum suspended_state next)
|
||||
disconnect_counter);
|
||||
set_bit(SUSPEND_DISCONNECTING, hdev->suspend_tasks);
|
||||
}
|
||||
} else if (next == BT_SUSPEND_COMPLETE) {
|
||||
} else if (next == BT_SUSPEND_CONFIGURE_WAKE) {
|
||||
/* Unpause to take care of updating scanning params */
|
||||
hdev->scanning_paused = false;
|
||||
/* Enable event filter for paired devices */
|
||||
@ -1447,7 +1447,7 @@ void __hci_req_update_scan_rsp_data(struct hci_request *req, u8 instance)
|
||||
memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
|
||||
hdev->scan_rsp_data_len = len;
|
||||
|
||||
cp.handle = 0;
|
||||
cp.handle = instance;
|
||||
cp.length = len;
|
||||
cp.operation = LE_SET_ADV_DATA_OP_COMPLETE;
|
||||
cp.frag_pref = LE_SET_ADV_DATA_NO_FRAG;
|
||||
@ -1591,7 +1591,7 @@ void __hci_req_update_adv_data(struct hci_request *req, u8 instance)
|
||||
hdev->adv_data_len = len;
|
||||
|
||||
cp.length = len;
|
||||
cp.handle = 0;
|
||||
cp.handle = instance;
|
||||
cp.operation = LE_SET_ADV_DATA_OP_COMPLETE;
|
||||
cp.frag_pref = LE_SET_ADV_DATA_NO_FRAG;
|
||||
|
||||
@ -1876,7 +1876,7 @@ int __hci_req_setup_ext_adv_instance(struct hci_request *req, u8 instance)
|
||||
|
||||
memset(&cp, 0, sizeof(cp));
|
||||
|
||||
cp.handle = 0;
|
||||
cp.handle = instance;
|
||||
bacpy(&cp.bdaddr, &random_addr);
|
||||
|
||||
hci_req_add(req,
|
||||
|
@ -1579,11 +1579,13 @@ static int hci_mgmt_cmd(struct hci_mgmt_chan *chan, struct sock *sk,
|
||||
}
|
||||
}
|
||||
|
||||
no_hdev = (handler->flags & HCI_MGMT_NO_HDEV);
|
||||
if (no_hdev != !hdev) {
|
||||
err = mgmt_cmd_status(sk, index, opcode,
|
||||
MGMT_STATUS_INVALID_INDEX);
|
||||
goto done;
|
||||
if (!(handler->flags & HCI_MGMT_HDEV_OPTIONAL)) {
|
||||
no_hdev = (handler->flags & HCI_MGMT_NO_HDEV);
|
||||
if (no_hdev != !hdev) {
|
||||
err = mgmt_cmd_status(sk, index, opcode,
|
||||
MGMT_STATUS_INVALID_INDEX);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
var_len = (handler->flags & HCI_MGMT_VAR_LEN);
|
||||
|
@ -5927,7 +5927,7 @@ static inline int l2cap_ecred_conn_req(struct l2cap_conn *conn,
|
||||
if (!enable_ecred)
|
||||
return -EINVAL;
|
||||
|
||||
if (cmd_len < sizeof(*req) || cmd_len - sizeof(*req) % sizeof(u16)) {
|
||||
if (cmd_len < sizeof(*req) || (cmd_len - sizeof(*req)) % sizeof(u16)) {
|
||||
result = L2CAP_CR_LE_INVALID_PARAMS;
|
||||
goto response;
|
||||
}
|
||||
@ -5964,7 +5964,7 @@ static inline int l2cap_ecred_conn_req(struct l2cap_conn *conn,
|
||||
}
|
||||
|
||||
result = L2CAP_CR_LE_SUCCESS;
|
||||
cmd_len -= sizeof(req);
|
||||
cmd_len -= sizeof(*req);
|
||||
num_scid = cmd_len / sizeof(u16);
|
||||
|
||||
for (i = 0; i < num_scid; i++) {
|
||||
|
@ -1271,14 +1271,21 @@ static int l2cap_sock_shutdown(struct socket *sock, int how)
|
||||
struct l2cap_conn *conn;
|
||||
int err = 0;
|
||||
|
||||
BT_DBG("sock %p, sk %p", sock, sk);
|
||||
BT_DBG("sock %p, sk %p, how %d", sock, sk, how);
|
||||
|
||||
/* 'how' parameter is mapped to sk_shutdown as follows:
|
||||
* SHUT_RD (0) --> RCV_SHUTDOWN (1)
|
||||
* SHUT_WR (1) --> SEND_SHUTDOWN (2)
|
||||
* SHUT_RDWR (2) --> SHUTDOWN_MASK (3)
|
||||
*/
|
||||
how++;
|
||||
|
||||
if (!sk)
|
||||
return 0;
|
||||
|
||||
lock_sock(sk);
|
||||
|
||||
if (sk->sk_shutdown)
|
||||
if ((sk->sk_shutdown & how) == how)
|
||||
goto shutdown_already;
|
||||
|
||||
BT_DBG("Handling sock shutdown");
|
||||
@ -1301,11 +1308,20 @@ static int l2cap_sock_shutdown(struct socket *sock, int how)
|
||||
* has already been actioned to close the L2CAP
|
||||
* link such as by l2cap_disconnection_req().
|
||||
*/
|
||||
if (sk->sk_shutdown)
|
||||
goto has_shutdown;
|
||||
if ((sk->sk_shutdown & how) == how)
|
||||
goto shutdown_matched;
|
||||
}
|
||||
|
||||
sk->sk_shutdown = SHUTDOWN_MASK;
|
||||
/* Try setting the RCV_SHUTDOWN bit, return early if SEND_SHUTDOWN
|
||||
* is already set
|
||||
*/
|
||||
if ((how & RCV_SHUTDOWN) && !(sk->sk_shutdown & RCV_SHUTDOWN)) {
|
||||
sk->sk_shutdown |= RCV_SHUTDOWN;
|
||||
if ((sk->sk_shutdown & how) == how)
|
||||
goto shutdown_matched;
|
||||
}
|
||||
|
||||
sk->sk_shutdown |= SEND_SHUTDOWN;
|
||||
release_sock(sk);
|
||||
|
||||
l2cap_chan_lock(chan);
|
||||
@ -1335,7 +1351,7 @@ static int l2cap_sock_shutdown(struct socket *sock, int how)
|
||||
err = bt_sock_wait_state(sk, BT_CLOSED,
|
||||
sk->sk_lingertime);
|
||||
|
||||
has_shutdown:
|
||||
shutdown_matched:
|
||||
l2cap_chan_put(chan);
|
||||
sock_put(sk);
|
||||
|
||||
@ -1363,7 +1379,7 @@ static int l2cap_sock_release(struct socket *sock)
|
||||
|
||||
bt_sock_unlink(&l2cap_sk_list, sk);
|
||||
|
||||
err = l2cap_sock_shutdown(sock, 2);
|
||||
err = l2cap_sock_shutdown(sock, SHUT_RDWR);
|
||||
chan = l2cap_pi(sk)->chan;
|
||||
|
||||
l2cap_chan_hold(chan);
|
||||
|
@ -183,6 +183,39 @@ void bt_err(const char *format, ...)
|
||||
}
|
||||
EXPORT_SYMBOL(bt_err);
|
||||
|
||||
#ifdef CONFIG_BT_FEATURE_DEBUG
|
||||
static bool debug_enable;
|
||||
|
||||
void bt_dbg_set(bool enable)
|
||||
{
|
||||
debug_enable = enable;
|
||||
}
|
||||
|
||||
bool bt_dbg_get(void)
|
||||
{
|
||||
return debug_enable;
|
||||
}
|
||||
|
||||
void bt_dbg(const char *format, ...)
|
||||
{
|
||||
struct va_format vaf;
|
||||
va_list args;
|
||||
|
||||
if (likely(!debug_enable))
|
||||
return;
|
||||
|
||||
va_start(args, format);
|
||||
|
||||
vaf.fmt = format;
|
||||
vaf.va = &args;
|
||||
|
||||
printk(KERN_DEBUG pr_fmt("%pV"), &vaf);
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
EXPORT_SYMBOL(bt_dbg);
|
||||
#endif
|
||||
|
||||
void bt_warn_ratelimited(const char *format, ...)
|
||||
{
|
||||
struct va_format vaf;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -508,7 +508,7 @@ bool smp_irk_matches(struct hci_dev *hdev, const u8 irk[16],
|
||||
if (!chan || !chan->data)
|
||||
return false;
|
||||
|
||||
BT_DBG("RPA %pMR IRK %*phN", bdaddr, 16, irk);
|
||||
bt_dev_dbg(hdev, "RPA %pMR IRK %*phN", bdaddr, 16, irk);
|
||||
|
||||
err = smp_ah(irk, &bdaddr->b[3], hash);
|
||||
if (err)
|
||||
@ -534,7 +534,7 @@ int smp_generate_rpa(struct hci_dev *hdev, const u8 irk[16], bdaddr_t *rpa)
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
BT_DBG("RPA %pMR", rpa);
|
||||
bt_dev_dbg(hdev, "RPA %pMR", rpa);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -551,7 +551,7 @@ int smp_generate_oob(struct hci_dev *hdev, u8 hash[16], u8 rand[16])
|
||||
smp = chan->data;
|
||||
|
||||
if (hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS)) {
|
||||
BT_DBG("Using debug keys");
|
||||
bt_dev_dbg(hdev, "Using debug keys");
|
||||
err = set_ecdh_privkey(smp->tfm_ecdh, debug_sk);
|
||||
if (err)
|
||||
return err;
|
||||
@ -1867,7 +1867,7 @@ static u8 sc_send_public_key(struct smp_chan *smp)
|
||||
{
|
||||
struct hci_dev *hdev = smp->conn->hcon->hdev;
|
||||
|
||||
BT_DBG("");
|
||||
bt_dev_dbg(hdev, "");
|
||||
|
||||
if (test_bit(SMP_FLAG_LOCAL_OOB, &smp->flags)) {
|
||||
struct l2cap_chan *chan = hdev->smp_data;
|
||||
|
Loading…
Reference in New Issue
Block a user