aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2021-04-08 14:19:32 -0700
committerDavid S. Miller <davem@davemloft.net>2021-04-08 14:19:32 -0700
commit4438669eb703d1a7416c2b19a8a15b0400b36738 (patch)
treea0281259b75a99f677630522bbe71fa0df405b14
parentMerge branch '100GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next-queue (diff)
parentBluetooth: Allow Microsoft extension to indicate curve validation (diff)
downloadlinux-dev-4438669eb703d1a7416c2b19a8a15b0400b36738.tar.xz
linux-dev-4438669eb703d1a7416c2b19a8a15b0400b36738.zip
Merge tag 'for-net-next-2021-04-08' 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: - Proper support for BCM4330 and BMC4334 - Various improvements for firmware download of Intel controllers - Update management interface revision to 20 - Support for AOSP HCI vendor commands - Initial Virtio support ==================== Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--Documentation/devicetree/bindings/net/broadcom-bluetooth.txt56
-rw-r--r--Documentation/devicetree/bindings/net/broadcom-bluetooth.yaml118
-rw-r--r--Documentation/devicetree/bindings/serial/ingenic,uart.yaml2
-rw-r--r--drivers/bluetooth/Kconfig10
-rw-r--r--drivers/bluetooth/Makefile2
-rw-r--r--drivers/bluetooth/btintel.c232
-rw-r--r--drivers/bluetooth/btintel.h19
-rw-r--r--drivers/bluetooth/btusb.c408
-rw-r--r--drivers/bluetooth/hci_bcm.c19
-rw-r--r--drivers/bluetooth/hci_intel.c7
-rw-r--r--drivers/bluetooth/hci_qca.c17
-rw-r--r--drivers/bluetooth/virtio_bt.c401
-rw-r--r--include/net/bluetooth/hci.h1
-rw-r--r--include/net/bluetooth/hci_core.h17
-rw-r--r--include/net/bluetooth/l2cap.h1
-rw-r--r--include/net/bluetooth/mgmt.h1
-rw-r--r--include/uapi/linux/virtio_bt.h31
-rw-r--r--include/uapi/linux/virtio_ids.h1
-rw-r--r--net/bluetooth/6lowpan.c5
-rw-r--r--net/bluetooth/Kconfig7
-rw-r--r--net/bluetooth/Makefile1
-rw-r--r--net/bluetooth/aosp.c35
-rw-r--r--net/bluetooth/aosp.h16
-rw-r--r--net/bluetooth/ecdh_helper.h2
-rw-r--r--net/bluetooth/hci_conn.c14
-rw-r--r--net/bluetooth/hci_core.c5
-rw-r--r--net/bluetooth/hci_debugfs.c8
-rw-r--r--net/bluetooth/hci_event.c50
-rw-r--r--net/bluetooth/hci_request.c67
-rw-r--r--net/bluetooth/l2cap_core.c43
-rw-r--r--net/bluetooth/l2cap_sock.c8
-rw-r--r--net/bluetooth/mgmt.c19
-rw-r--r--net/bluetooth/msft.c8
-rw-r--r--net/bluetooth/msft.h6
-rw-r--r--net/bluetooth/sco.c4
-rw-r--r--net/bluetooth/smp.c113
36 files changed, 1289 insertions, 465 deletions
diff --git a/Documentation/devicetree/bindings/net/broadcom-bluetooth.txt b/Documentation/devicetree/bindings/net/broadcom-bluetooth.txt
deleted file mode 100644
index a7d57ba5f2ac..000000000000
--- a/Documentation/devicetree/bindings/net/broadcom-bluetooth.txt
+++ /dev/null
@@ -1,56 +0,0 @@
-Broadcom Bluetooth Chips
----------------------
-
-This documents the binding structure and common properties for serial
-attached Broadcom devices.
-
-Serial attached Broadcom devices shall be a child node of the host UART
-device the slave device is attached to.
-
-Required properties:
-
- - compatible: should contain one of the following:
- * "brcm,bcm20702a1"
- * "brcm,bcm4329-bt"
- * "brcm,bcm4330-bt"
- * "brcm,bcm43438-bt"
- * "brcm,bcm4345c5"
- * "brcm,bcm43540-bt"
- * "brcm,bcm4335a0"
-
-Optional properties:
-
- - max-speed: see Documentation/devicetree/bindings/serial/serial.yaml
- - shutdown-gpios: GPIO specifier, used to enable the BT module
- - device-wakeup-gpios: GPIO specifier, used to wakeup the controller
- - host-wakeup-gpios: GPIO specifier, used to wakeup the host processor.
- deprecated, replaced by interrupts and
- "host-wakeup" interrupt-names
- - clocks: 1 or 2 clocks as defined in clock-names below, in that order
- - clock-names: names for clock inputs, matching the clocks given
- - "extclk": deprecated, replaced by "txco"
- - "txco": external reference clock (not a standalone crystal)
- - "lpo": external low power 32.768 kHz clock
- - vbat-supply: phandle to regulator supply for VBAT
- - vddio-supply: phandle to regulator supply for VDDIO
- - brcm,bt-pcm-int-params: configure PCM parameters via a 5-byte array
- - sco-routing: 0 = PCM, 1 = Transport, 2 = Codec, 3 = I2S
- - pcm-interface-rate: 128KBps, 256KBps, 512KBps, 1024KBps, 2048KBps
- - pcm-frame-type: short, long
- - pcm-sync-mode: slave, master
- - pcm-clock-mode: slave, master
- - interrupts: must be one, used to wakeup the host processor
- - interrupt-names: must be "host-wakeup"
-
-Example:
-
-&uart2 {
- pinctrl-names = "default";
- pinctrl-0 = <&uart2_pins>;
-
- bluetooth {
- compatible = "brcm,bcm43438-bt";
- max-speed = <921600>;
- brcm,bt-pcm-int-params = [01 02 00 01 01];
- };
-};
diff --git a/Documentation/devicetree/bindings/net/broadcom-bluetooth.yaml b/Documentation/devicetree/bindings/net/broadcom-bluetooth.yaml
new file mode 100644
index 000000000000..fbdc2083bec4
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/broadcom-bluetooth.yaml
@@ -0,0 +1,118 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/broadcom-bluetooth.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Broadcom Bluetooth Chips
+
+maintainers:
+ - Linus Walleij <linus.walleij@linaro.org>
+
+description:
+ This binding describes Broadcom UART-attached bluetooth chips.
+
+properties:
+ compatible:
+ enum:
+ - brcm,bcm20702a1
+ - brcm,bcm4329-bt
+ - brcm,bcm4330-bt
+ - brcm,bcm4334-bt
+ - brcm,bcm43438-bt
+ - brcm,bcm4345c5
+ - brcm,bcm43540-bt
+ - brcm,bcm4335a0
+
+ shutdown-gpios:
+ maxItems: 1
+ description: GPIO specifier for the line BT_REG_ON used to
+ power on the BT module
+
+ reset-gpios:
+ maxItems: 1
+ description: GPIO specifier for the line BT_RST_N used to
+ reset the BT module. This should be marked as
+ GPIO_ACTIVE_LOW.
+
+ device-wakeup-gpios:
+ maxItems: 1
+ description: GPIO specifier for the line BT_WAKE used to
+ wakeup the controller. This is using the BT_GPIO_0
+ pin on the chip when in use.
+
+ host-wakeup-gpios:
+ maxItems: 1
+ deprecated: true
+ description: GPIO specifier for the line HOST_WAKE used
+ to wakeup the host processor. This is using he BT_GPIO_1
+ pin on the chip when in use. This is deprecated and replaced
+ by interrupts and "host-wakeup" interrupt-names
+
+ clocks:
+ maxItems: 2
+ description: 1 or 2 clocks as defined in clock-names below,
+ in that order
+
+ clock-names:
+ description: Names of the 1 to 2 supplied clocks
+ items:
+ - const: txco
+ - const: lpo
+ - const: extclk
+
+ vbat-supply:
+ description: phandle to regulator supply for VBAT
+
+ vddio-supply:
+ description: phandle to regulator supply for VDDIO
+
+ brcm,bt-pcm-int-params:
+ $ref: /schemas/types.yaml#/definitions/uint8-array
+ minItems: 5
+ maxItems: 5
+ description: |-
+ configure PCM parameters via a 5-byte array:
+ sco-routing: 0 = PCM, 1 = Transport, 2 = Codec, 3 = I2S
+ pcm-interface-rate: 128KBps, 256KBps, 512KBps, 1024KBps, 2048KBps
+ pcm-frame-type: short, long
+ pcm-sync-mode: slave, master
+ pcm-clock-mode: slave, master
+
+ interrupts:
+ items:
+ - description: Handle to the line HOST_WAKE used to wake
+ up the host processor. This uses the BT_GPIO_1 pin on
+ the chip when in use.
+
+ interrupt-names:
+ items:
+ - const: host-wakeup
+
+ max-speed: true
+ current-speed: true
+
+required:
+ - compatible
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ uart {
+ uart-has-rtscts;
+
+ bluetooth {
+ compatible = "brcm,bcm4330-bt";
+ max-speed = <921600>;
+ brcm,bt-pcm-int-params = [01 02 00 01 01];
+ shutdown-gpios = <&gpio 30 GPIO_ACTIVE_HIGH>;
+ device-wakeup-gpios = <&gpio 7 GPIO_ACTIVE_HIGH>;
+ reset-gpios = <&gpio 9 GPIO_ACTIVE_LOW>;
+ interrupt-parent = <&gpio>;
+ interrupts = <8 IRQ_TYPE_EDGE_FALLING>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/serial/ingenic,uart.yaml b/Documentation/devicetree/bindings/serial/ingenic,uart.yaml
index 559213899d73..7748d8c3bab8 100644
--- a/Documentation/devicetree/bindings/serial/ingenic,uart.yaml
+++ b/Documentation/devicetree/bindings/serial/ingenic,uart.yaml
@@ -91,7 +91,7 @@ examples:
bluetooth {
compatible = "brcm,bcm4330-bt";
reset-gpios = <&gpf 8 GPIO_ACTIVE_HIGH>;
- vcc-supply = <&wlan0_power>;
+ vbat-supply = <&wlan0_power>;
device-wakeup-gpios = <&gpf 5 GPIO_ACTIVE_HIGH>;
host-wakeup-gpios = <&gpf 6 GPIO_ACTIVE_HIGH>;
shutdown-gpios = <&gpf 4 GPIO_ACTIVE_LOW>;
diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig
index 4e73a531b377..851842372c9b 100644
--- a/drivers/bluetooth/Kconfig
+++ b/drivers/bluetooth/Kconfig
@@ -425,4 +425,14 @@ config BT_HCIRSI
Say Y here to compile support for HCI over Redpine into the
kernel or say M to compile as a module.
+config BT_VIRTIO
+ tristate "Virtio Bluetooth driver"
+ depends on VIRTIO
+ help
+ Virtio Bluetooth support driver.
+ This driver supports Virtio Bluetooth devices.
+
+ Say Y here to compile support for HCI over Virtio into the
+ kernel or say M to compile as a module.
+
endmenu
diff --git a/drivers/bluetooth/Makefile b/drivers/bluetooth/Makefile
index 1a58a3ae142c..16286ea2655d 100644
--- a/drivers/bluetooth/Makefile
+++ b/drivers/bluetooth/Makefile
@@ -26,6 +26,8 @@ obj-$(CONFIG_BT_BCM) += btbcm.o
obj-$(CONFIG_BT_RTL) += btrtl.o
obj-$(CONFIG_BT_QCA) += btqca.o
+obj-$(CONFIG_BT_VIRTIO) += virtio_bt.o
+
obj-$(CONFIG_BT_HCIUART_NOKIA) += hci_nokia.o
obj-$(CONFIG_BT_HCIRSI) += btrsi.o
diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c
index 88ce5f0ffc4b..e44b6993cf91 100644
--- a/drivers/bluetooth/btintel.c
+++ b/drivers/bluetooth/btintel.c
@@ -24,6 +24,14 @@
#define ECDSA_OFFSET 644
#define ECDSA_HEADER_LEN 320
+#define CMD_WRITE_BOOT_PARAMS 0xfc0e
+struct cmd_write_boot_params {
+ u32 boot_addr;
+ u8 fw_build_num;
+ u8 fw_build_ww;
+ u8 fw_build_yy;
+} __packed;
+
int btintel_check_bdaddr(struct hci_dev *hdev)
{
struct hci_rp_read_bd_addr *bda;
@@ -208,10 +216,39 @@ void btintel_hw_error(struct hci_dev *hdev, u8 code)
}
EXPORT_SYMBOL_GPL(btintel_hw_error);
-void btintel_version_info(struct hci_dev *hdev, struct intel_version *ver)
+int btintel_version_info(struct hci_dev *hdev, struct intel_version *ver)
{
const char *variant;
+ /* The hardware platform number has a fixed value of 0x37 and
+ * for now only accept this single value.
+ */
+ if (ver->hw_platform != 0x37) {
+ bt_dev_err(hdev, "Unsupported Intel hardware platform (%u)",
+ ver->hw_platform);
+ return -EINVAL;
+ }
+
+ /* Check for supported iBT hardware variants of this firmware
+ * loading method.
+ *
+ * This check has been put in place to ensure correct forward
+ * compatibility options when newer hardware variants come along.
+ */
+ switch (ver->hw_variant) {
+ case 0x0b: /* SfP */
+ case 0x0c: /* WsP */
+ case 0x11: /* JfP */
+ case 0x12: /* ThP */
+ case 0x13: /* HrP */
+ case 0x14: /* CcP */
+ break;
+ default:
+ bt_dev_err(hdev, "Unsupported Intel hardware variant (%u)",
+ ver->hw_variant);
+ return -EINVAL;
+ }
+
switch (ver->fw_variant) {
case 0x06:
variant = "Bootloader";
@@ -220,13 +257,16 @@ void btintel_version_info(struct hci_dev *hdev, struct intel_version *ver)
variant = "Firmware";
break;
default:
- return;
+ bt_dev_err(hdev, "Unsupported firmware variant(%02x)", ver->fw_variant);
+ return -EINVAL;
}
bt_dev_info(hdev, "%s revision %u.%u build %u week %u %u",
variant, ver->fw_revision >> 4, ver->fw_revision & 0x0f,
ver->fw_build_num, ver->fw_build_ww,
2000 + ver->fw_build_yy);
+
+ return 0;
}
EXPORT_SYMBOL_GPL(btintel_version_info);
@@ -364,13 +404,56 @@ int btintel_read_version(struct hci_dev *hdev, struct intel_version *ver)
}
EXPORT_SYMBOL_GPL(btintel_read_version);
-void btintel_version_info_tlv(struct hci_dev *hdev, struct intel_version_tlv *version)
+int btintel_version_info_tlv(struct hci_dev *hdev, struct intel_version_tlv *version)
{
const char *variant;
+ /* The hardware platform number has a fixed value of 0x37 and
+ * for now only accept this single value.
+ */
+ if (INTEL_HW_PLATFORM(version->cnvi_bt) != 0x37) {
+ bt_dev_err(hdev, "Unsupported Intel hardware platform (0x%2x)",
+ INTEL_HW_PLATFORM(version->cnvi_bt));
+ return -EINVAL;
+ }
+
+ /* Check for supported iBT hardware variants of this firmware
+ * loading method.
+ *
+ * This check has been put in place to ensure correct forward
+ * compatibility options when newer hardware variants come along.
+ */
+ switch (INTEL_HW_VARIANT(version->cnvi_bt)) {
+ case 0x17: /* TyP */
+ case 0x18: /* Slr */
+ case 0x19: /* Slr-F */
+ break;
+ default:
+ bt_dev_err(hdev, "Unsupported Intel hardware variant (0x%x)",
+ INTEL_HW_VARIANT(version->cnvi_bt));
+ return -EINVAL;
+ }
+
switch (version->img_type) {
case 0x01:
variant = "Bootloader";
+ /* It is required that every single firmware fragment is acknowledged
+ * with a command complete event. If the boot parameters indicate
+ * that this bootloader does not send them, then abort the setup.
+ */
+ if (version->limited_cce != 0x00) {
+ bt_dev_err(hdev, "Unsupported Intel firmware loading method (0x%x)",
+ version->limited_cce);
+ return -EINVAL;
+ }
+
+ /* Secure boot engine type should be either 1 (ECDSA) or 0 (RSA) */
+ if (version->sbe_type > 0x01) {
+ bt_dev_err(hdev, "Unsupported Intel secure boot engine type (0x%x)",
+ version->sbe_type);
+ return -EINVAL;
+ }
+
bt_dev_info(hdev, "Device revision is %u", version->dev_rev_id);
bt_dev_info(hdev, "Secure boot is %s",
version->secure_boot ? "enabled" : "disabled");
@@ -389,15 +472,14 @@ void btintel_version_info_tlv(struct hci_dev *hdev, struct intel_version_tlv *ve
break;
default:
bt_dev_err(hdev, "Unsupported image type(%02x)", version->img_type);
- goto done;
+ return -EINVAL;
}
bt_dev_info(hdev, "%s timestamp %u.%u buildtype %u build %u", variant,
2000 + (version->timestamp >> 8), version->timestamp & 0xff,
version->build_type, version->build_num);
-done:
- return;
+ return 0;
}
EXPORT_SYMBOL_GPL(btintel_version_info_tlv);
@@ -455,12 +537,23 @@ int btintel_read_version_tlv(struct hci_dev *hdev, struct intel_version_tlv *ver
version->img_type = tlv->val[0];
break;
case INTEL_TLV_TIME_STAMP:
+ /* If image type is Operational firmware (0x03), then
+ * running FW Calendar Week and Year information can
+ * be extracted from Timestamp information
+ */
+ version->min_fw_build_cw = tlv->val[0];
+ version->min_fw_build_yy = tlv->val[1];
version->timestamp = get_unaligned_le16(tlv->val);
break;
case INTEL_TLV_BUILD_TYPE:
version->build_type = tlv->val[0];
break;
case INTEL_TLV_BUILD_NUM:
+ /* If image type is Operational firmware (0x03), then
+ * running FW build number can be extracted from the
+ * Build information
+ */
+ version->min_fw_build_nn = tlv->val[0];
version->build_num = get_unaligned_le32(tlv->val);
break;
case INTEL_TLV_SECURE_BOOT:
@@ -841,7 +934,7 @@ static int btintel_sfi_ecdsa_header_secure_send(struct hci_dev *hdev,
static int btintel_download_firmware_payload(struct hci_dev *hdev,
const struct firmware *fw,
- u32 *boot_param, size_t offset)
+ size_t offset)
{
int err;
const u8 *fw_ptr;
@@ -854,20 +947,6 @@ static int btintel_download_firmware_payload(struct hci_dev *hdev,
while (fw_ptr - fw->data < fw->size) {
struct hci_command_hdr *cmd = (void *)(fw_ptr + frag_len);
- /* Each SKU has a different reset parameter to use in the
- * HCI_Intel_Reset command and it is embedded in the firmware
- * data. So, instead of using static value per SKU, check
- * the firmware data and save it for later use.
- */
- if (le16_to_cpu(cmd->opcode) == 0xfc0e) {
- /* The boot parameter is the first 32-bit value
- * and rest of 3 octets are reserved.
- */
- *boot_param = get_unaligned_le32(fw_ptr + sizeof(*cmd));
-
- bt_dev_dbg(hdev, "boot_param=0x%x", *boot_param);
- }
-
frag_len += sizeof(*cmd) + cmd->plen;
/* The parameter length of the secure send command requires
@@ -896,28 +975,131 @@ done:
return err;
}
+static bool btintel_firmware_version(struct hci_dev *hdev,
+ u8 num, u8 ww, u8 yy,
+ const struct firmware *fw,
+ u32 *boot_addr)
+{
+ const u8 *fw_ptr;
+
+ fw_ptr = fw->data;
+
+ while (fw_ptr - fw->data < fw->size) {
+ struct hci_command_hdr *cmd = (void *)(fw_ptr);
+
+ /* Each SKU has a different reset parameter to use in the
+ * HCI_Intel_Reset command and it is embedded in the firmware
+ * data. So, instead of using static value per SKU, check
+ * the firmware data and save it for later use.
+ */
+ if (le16_to_cpu(cmd->opcode) == CMD_WRITE_BOOT_PARAMS) {
+ struct cmd_write_boot_params *params;
+
+ params = (void *)(fw_ptr + sizeof(*cmd));
+
+ bt_dev_info(hdev, "Boot Address: 0x%x",
+ le32_to_cpu(params->boot_addr));
+
+ bt_dev_info(hdev, "Firmware Version: %u-%u.%u",
+ params->fw_build_num, params->fw_build_ww,
+ params->fw_build_yy);
+
+ return (num == params->fw_build_num &&
+ ww == params->fw_build_ww &&
+ yy == params->fw_build_yy);
+ }
+
+ fw_ptr += sizeof(*cmd) + cmd->plen;
+ }
+
+ return false;
+}
+
int btintel_download_firmware(struct hci_dev *hdev,
+ struct intel_version *ver,
const struct firmware *fw,
u32 *boot_param)
{
int err;
+ /* SfP and WsP don't seem to update the firmware version on file
+ * so version checking is currently not possible.
+ */
+ switch (ver->hw_variant) {
+ case 0x0b: /* SfP */
+ case 0x0c: /* WsP */
+ /* Skip version checking */
+ break;
+ default:
+ /* Skip reading firmware file version in bootloader mode */
+ if (ver->fw_variant == 0x06)
+ break;
+
+ /* Skip download if firmware has the same version */
+ if (btintel_firmware_version(hdev, ver->fw_build_num,
+ ver->fw_build_ww, ver->fw_build_yy,
+ fw, boot_param)) {
+ bt_dev_info(hdev, "Firmware already loaded");
+ /* Return -EALREADY to indicate that the firmware has
+ * already been loaded.
+ */
+ return -EALREADY;
+ }
+ }
+
+ /* The firmware variant determines if the device is in bootloader
+ * mode or is running operational firmware. The value 0x06 identifies
+ * the bootloader and the value 0x23 identifies the operational
+ * firmware.
+ *
+ * If the firmware version has changed that means it needs to be reset
+ * to bootloader when operational so the new firmware can be loaded.
+ */
+ if (ver->fw_variant == 0x23)
+ return -EINVAL;
+
err = btintel_sfi_rsa_header_secure_send(hdev, fw);
if (err)
return err;
- return btintel_download_firmware_payload(hdev, fw, boot_param,
- RSA_HEADER_LEN);
+ return btintel_download_firmware_payload(hdev, fw, RSA_HEADER_LEN);
}
EXPORT_SYMBOL_GPL(btintel_download_firmware);
int btintel_download_firmware_newgen(struct hci_dev *hdev,
+ struct intel_version_tlv *ver,
const struct firmware *fw, u32 *boot_param,
u8 hw_variant, u8 sbe_type)
{
int err;
u32 css_header_ver;
+ /* Skip reading firmware file version in bootloader mode */
+ if (ver->img_type != 0x01) {
+ /* Skip download if firmware has the same version */
+ if (btintel_firmware_version(hdev, ver->min_fw_build_nn,
+ ver->min_fw_build_cw,
+ ver->min_fw_build_yy,
+ fw, boot_param)) {
+ bt_dev_info(hdev, "Firmware already loaded");
+ /* Return -EALREADY to indicate that firmware has
+ * already been loaded.
+ */
+ return -EALREADY;
+ }
+ }
+
+ /* The firmware variant determines if the device is in bootloader
+ * mode or is running operational firmware. The value 0x01 identifies
+ * the bootloader and the value 0x03 identifies the operational
+ * firmware.
+ *
+ * If the firmware version has changed that means it needs to be reset
+ * to bootloader when operational so the new firmware can be loaded.
+ */
+ if (ver->img_type == 0x03)
+ return -EINVAL;
+
/* iBT hardware variants 0x0b, 0x0c, 0x11, 0x12, 0x13, 0x14 support
* only RSA secure boot engine. Hence, the corresponding sfi file will
* have RSA header of 644 bytes followed by Command Buffer.
@@ -947,7 +1129,7 @@ int btintel_download_firmware_newgen(struct hci_dev *hdev,
if (err)
return err;
- err = btintel_download_firmware_payload(hdev, fw, boot_param, RSA_HEADER_LEN);
+ err = btintel_download_firmware_payload(hdev, fw, RSA_HEADER_LEN);
if (err)
return err;
} else if (hw_variant >= 0x17) {
@@ -968,7 +1150,6 @@ int btintel_download_firmware_newgen(struct hci_dev *hdev,
return err;
err = btintel_download_firmware_payload(hdev, fw,
- boot_param,
RSA_HEADER_LEN + ECDSA_HEADER_LEN);
if (err)
return err;
@@ -978,7 +1159,6 @@ int btintel_download_firmware_newgen(struct hci_dev *hdev,
return err;
err = btintel_download_firmware_payload(hdev, fw,
- boot_param,
RSA_HEADER_LEN + ECDSA_HEADER_LEN);
if (err)
return err;
diff --git a/drivers/bluetooth/btintel.h b/drivers/bluetooth/btintel.h
index 6511b091caf5..d184064a5e7c 100644
--- a/drivers/bluetooth/btintel.h
+++ b/drivers/bluetooth/btintel.h
@@ -148,8 +148,8 @@ int btintel_set_diag(struct hci_dev *hdev, bool enable);
int btintel_set_diag_mfg(struct hci_dev *hdev, bool enable);
void btintel_hw_error(struct hci_dev *hdev, u8 code);
-void btintel_version_info(struct hci_dev *hdev, struct intel_version *ver);
-void btintel_version_info_tlv(struct hci_dev *hdev, struct intel_version_tlv *version);
+int btintel_version_info(struct hci_dev *hdev, struct intel_version *ver);
+int btintel_version_info_tlv(struct hci_dev *hdev, struct intel_version_tlv *version);
int btintel_secure_send(struct hci_dev *hdev, u8 fragment_type, u32 plen,
const void *param);
int btintel_load_ddc_config(struct hci_dev *hdev, const char *ddc_name);
@@ -163,9 +163,10 @@ struct regmap *btintel_regmap_init(struct hci_dev *hdev, u16 opcode_read,
int btintel_send_intel_reset(struct hci_dev *hdev, u32 boot_param);
int btintel_read_boot_params(struct hci_dev *hdev,
struct intel_boot_params *params);
-int btintel_download_firmware(struct hci_dev *dev, const struct firmware *fw,
- u32 *boot_param);
+int btintel_download_firmware(struct hci_dev *dev, struct intel_version *ver,
+ const struct firmware *fw, u32 *boot_param);
int btintel_download_firmware_newgen(struct hci_dev *hdev,
+ struct intel_version_tlv *ver,
const struct firmware *fw,
u32 *boot_param, u8 hw_variant,
u8 sbe_type);
@@ -210,14 +211,16 @@ static inline void btintel_hw_error(struct hci_dev *hdev, u8 code)
{
}
-static inline void btintel_version_info(struct hci_dev *hdev,
- struct intel_version *ver)
+static inline int btintel_version_info(struct hci_dev *hdev,
+ struct intel_version *ver)
{
+ return -EOPNOTSUPP;
}
-static inline void btintel_version_info_tlv(struct hci_dev *hdev,
- struct intel_version_tlv *version)
+static inline int btintel_version_info_tlv(struct hci_dev *hdev,
+ struct intel_version_tlv *version)
{
+ return -EOPNOTSUPP;
}
static inline int btintel_secure_send(struct hci_dev *hdev, u8 fragment_type,
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 52683fd22e05..192cb8c191bc 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -399,7 +399,9 @@ static const struct usb_device_id blacklist_table[] = {
/* MediaTek Bluetooth devices */
{ USB_VENDOR_AND_INTERFACE_INFO(0x0e8d, 0xe0, 0x01, 0x01),
- .driver_info = BTUSB_MEDIATEK },
+ .driver_info = BTUSB_MEDIATEK |
+ BTUSB_WIDEBAND_SPEECH |
+ BTUSB_VALID_LE_STATES },
/* Additional MediaTek MT7615E Bluetooth devices */
{ USB_DEVICE(0x13d3, 0x3560), .driver_info = BTUSB_MEDIATEK},
@@ -455,6 +457,8 @@ static const struct usb_device_id blacklist_table[] = {
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x0bda, 0xc123), .driver_info = BTUSB_REALTEK |
BTUSB_WIDEBAND_SPEECH },
+ { USB_DEVICE(0x0cb5, 0xc547), .driver_info = BTUSB_REALTEK |
+ BTUSB_WIDEBAND_SPEECH },
/* Silicon Wave based devices */
{ USB_DEVICE(0x0c10, 0x0000), .driver_info = BTUSB_SWAVE },
@@ -2400,7 +2404,7 @@ static int btusb_send_frame_intel(struct hci_dev *hdev, struct sk_buff *skb)
return -EILSEQ;
}
-static bool btusb_setup_intel_new_get_fw_name(struct intel_version *ver,
+static int btusb_setup_intel_new_get_fw_name(struct intel_version *ver,
struct intel_boot_params *params,
char *fw_name, size_t len,
const char *suffix)
@@ -2424,9 +2428,10 @@ static bool btusb_setup_intel_new_get_fw_name(struct intel_version *ver,
suffix);
break;
default:
- return false;
+ return -EINVAL;
}
- return true;
+
+ return 0;
}
static void btusb_setup_intel_newgen_get_fw_name(const struct intel_version_tlv *ver_tlv,
@@ -2444,6 +2449,44 @@ static void btusb_setup_intel_newgen_get_fw_name(const struct intel_version_tlv
suffix);
}
+static int btusb_download_wait(struct hci_dev *hdev, ktime_t calltime, int msec)
+{
+ struct btusb_data *data = hci_get_drvdata(hdev);
+ ktime_t delta, rettime;
+ unsigned long long duration;
+ int err;
+
+ set_bit(BTUSB_FIRMWARE_LOADED, &data->flags);
+
+ bt_dev_info(hdev, "Waiting for firmware download to complete");
+
+ err = wait_on_bit_timeout(&data->flags, BTUSB_DOWNLOADING,
+ TASK_INTERRUPTIBLE,
+ msecs_to_jiffies(msec));
+ if (err == -EINTR) {
+ bt_dev_err(hdev, "Firmware loading interrupted");
+ return err;
+ }
+
+ if (err) {
+ bt_dev_err(hdev, "Firmware loading timeout");
+ return -ETIMEDOUT;
+ }
+
+ if (test_bit(BTUSB_FIRMWARE_FAILED, &data->flags)) {
+ bt_dev_err(hdev, "Firmware loading failed");
+ return -ENOEXEC;
+ }
+
+ rettime = ktime_get();
+ delta = ktime_sub(rettime, calltime);
+ duration = (unsigned long long)ktime_to_ns(delta) >> 10;
+
+ bt_dev_info(hdev, "Firmware loaded in %llu usecs", duration);
+
+ return 0;
+}
+
static int btusb_intel_download_firmware_newgen(struct hci_dev *hdev,
struct intel_version_tlv *ver,
u32 *boot_param)
@@ -2452,19 +2495,11 @@ static int btusb_intel_download_firmware_newgen(struct hci_dev *hdev,
char fwname[64];
int err;
struct btusb_data *data = hci_get_drvdata(hdev);
+ ktime_t calltime;
if (!ver || !boot_param)
return -EINVAL;
- /* The hardware platform number has a fixed value of 0x37 and
- * for now only accept this single value.
- */
- if (INTEL_HW_PLATFORM(ver->cnvi_bt) != 0x37) {
- bt_dev_err(hdev, "Unsupported Intel hardware platform (0x%2x)",
- INTEL_HW_PLATFORM(ver->cnvi_bt));
- return -EINVAL;
- }
-
/* The firmware variant determines if the device is in bootloader
* mode or is running operational firmware. The value 0x03 identifies
* the bootloader and the value 0x23 identifies the operational
@@ -2481,50 +2516,6 @@ static int btusb_intel_download_firmware_newgen(struct hci_dev *hdev,
if (ver->img_type == 0x03) {
clear_bit(BTUSB_BOOTLOADER, &data->flags);
btintel_check_bdaddr(hdev);
- return 0;
- }
-
- /* Check for supported iBT hardware variants of this firmware
- * loading method.
- *
- * This check has been put in place to ensure correct forward
- * compatibility options when newer hardware variants come along.
- */
- switch (INTEL_HW_VARIANT(ver->cnvi_bt)) {
- case 0x17: /* TyP */
- case 0x18: /* Slr */
- case 0x19: /* Slr-F */
- break;
- default:
- bt_dev_err(hdev, "Unsupported Intel hardware variant (0x%x)",
- INTEL_HW_VARIANT(ver->cnvi_bt));
- return -EINVAL;
- }
-
- /* If the device is not in bootloader mode, then the only possible
- * choice is to return an error and abort the device initialization.
- */
- if (ver->img_type != 0x01) {
- bt_dev_err(hdev, "Unsupported Intel firmware variant (0x%x)",
- ver->img_type);
- return -ENODEV;
- }
-
- /* It is required that every single firmware fragment is acknowledged
- * with a command complete event. If the boot parameters indicate
- * that this bootloader does not send them, then abort the setup.
- */
- if (ver->limited_cce != 0x00) {
- bt_dev_err(hdev, "Unsupported Intel firmware loading method (0x%x)",
- ver->limited_cce);
- return -EINVAL;
- }
-
- /* Secure boot engine type should be either 1 (ECDSA) or 0 (RSA) */
- if (ver->sbe_type > 0x01) {
- bt_dev_err(hdev, "Unsupported Intel secure boot engine type (0x%x)",
- ver->sbe_type);
- return -EINVAL;
}
/* If the OTP has no valid Bluetooth device address, then there will
@@ -2538,7 +2529,8 @@ static int btusb_intel_download_firmware_newgen(struct hci_dev *hdev,
btusb_setup_intel_newgen_get_fw_name(ver, fwname, sizeof(fwname), "sfi");
err = request_firmware(&fw, fwname, &hdev->dev);
if (err < 0) {
- bt_dev_err(hdev, "Failed to load Intel firmware file (%d)", err);
+ bt_dev_err(hdev, "Failed to load Intel firmware file %s (%d)",
+ fwname, err);
return err;
}
@@ -2551,22 +2543,28 @@ static int btusb_intel_download_firmware_newgen(struct hci_dev *hdev,
goto done;
}
+ calltime = ktime_get();
+
set_bit(BTUSB_DOWNLOADING, &data->flags);
/* Start firmware downloading and get boot parameter */
- err = btintel_download_firmware_newgen(hdev, fw, boot_param,
+ err = btintel_download_firmware_newgen(hdev, ver, fw, boot_param,
INTEL_HW_VARIANT(ver->cnvi_bt),
ver->sbe_type);
if (err < 0) {
+ if (err == -EALREADY) {
+ /* Firmware has already been loaded */
+ set_bit(BTUSB_FIRMWARE_LOADED, &data->flags);
+ err = 0;
+ goto done;
+ }
+
/* When FW download fails, send Intel Reset to retry
* FW download.
*/
btintel_reset_to_bootloader(hdev);
goto done;
}
- set_bit(BTUSB_FIRMWARE_LOADED, &data->flags);
-
- bt_dev_info(hdev, "Waiting for firmware download to complete");
/* Before switching the device into operational mode and with that
* booting the loaded firmware, wait for the bootloader notification
@@ -2579,26 +2577,9 @@ static int btusb_intel_download_firmware_newgen(struct hci_dev *hdev,
* and thus just timeout if that happens and fail the setup
* of this device.
*/
- err = wait_on_bit_timeout(&data->flags, BTUSB_DOWNLOADING,
- TASK_INTERRUPTIBLE,
- msecs_to_jiffies(5000));
- if (err == -EINTR) {
- bt_dev_err(hdev, "Firmware loading interrupted");
- goto done;
- }
-
- if (err) {
- bt_dev_err(hdev, "Firmware loading timeout");
- err = -ETIMEDOUT;
+ err = btusb_download_wait(hdev, calltime, 5000);
+ if (err == -ETIMEDOUT)
btintel_reset_to_bootloader(hdev);
- goto done;
- }
-
- if (test_bit(BTUSB_FIRMWARE_FAILED, &data->flags)) {
- bt_dev_err(hdev, "Firmware loading failed");
- err = -ENOEXEC;
- goto done;
- }
done:
release_firmware(fw);
@@ -2614,41 +2595,11 @@ static int btusb_intel_download_firmware(struct hci_dev *hdev,
char fwname[64];
int err;
struct btusb_data *data = hci_get_drvdata(hdev);
+ ktime_t calltime;
if (!ver || !params)
return -EINVAL;
- /* The hardware platform number has a fixed value of 0x37 and
- * for now only accept this single value.
- */
- if (ver->hw_platform != 0x37) {
- bt_dev_err(hdev, "Unsupported Intel hardware platform (%u)",
- ver->hw_platform);
- return -EINVAL;
- }
-
- /* Check for supported iBT hardware variants of this firmware
- * loading method.
- *
- * This check has been put in place to ensure correct forward
- * compatibility options when newer hardware variants come along.
- */
- switch (ver->hw_variant) {
- case 0x0b: /* SfP */
- case 0x0c: /* WsP */
- case 0x11: /* JfP */
- case 0x12: /* ThP */
- case 0x13: /* HrP */
- case 0x14: /* CcP */
- break;
- default:
- bt_dev_err(hdev, "Unsupported Intel hardware variant (%u)",
- ver->hw_variant);
- return -EINVAL;
- }
-
- btintel_version_info(hdev, ver);
-
/* The firmware variant determines if the device is in bootloader
* mode or is running operational firmware. The value 0x06 identifies
* the bootloader and the value 0x23 identifies the operational
@@ -2665,16 +2616,18 @@ static int btusb_intel_download_firmware(struct hci_dev *hdev,
if (ver->fw_variant == 0x23) {
clear_bit(BTUSB_BOOTLOADER, &data->flags);
btintel_check_bdaddr(hdev);
- return 0;
- }
- /* If the device is not in bootloader mode, then the only possible
- * choice is to return an error and abort the device initialization.
- */
- if (ver->fw_variant != 0x06) {
- bt_dev_err(hdev, "Unsupported Intel firmware variant (%u)",
- ver->fw_variant);
- return -ENODEV;
+ /* SfP and WsP don't seem to update the firmware version on file
+ * so version checking is currently possible.
+ */
+ switch (ver->hw_variant) {
+ case 0x0b: /* SfP */
+ case 0x0c: /* WsP */
+ return 0;
+ }
+
+ /* Proceed to download to check if the version matches */
+ goto download;
}
/* Read the secure boot parameters to identify the operating
@@ -2702,6 +2655,7 @@ static int btusb_intel_download_firmware(struct hci_dev *hdev,
set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks);
}
+download:
/* With this Intel bootloader only the hardware variant and device
* revision information are used to select the right firmware for SfP
* and WsP.
@@ -2725,14 +2679,15 @@ static int btusb_intel_download_firmware(struct hci_dev *hdev,
*/
err = btusb_setup_intel_new_get_fw_name(ver, params, fwname,
sizeof(fwname), "sfi");
- if (!err) {
+ if (err < 0) {
bt_dev_err(hdev, "Unsupported Intel firmware naming");
return -EINVAL;
}
err = request_firmware(&fw, fwname, &hdev->dev);
if (err < 0) {
- bt_dev_err(hdev, "Failed to load Intel firmware file (%d)", err);
+ bt_dev_err(hdev, "Failed to load Intel firmware file %s (%d)",
+ fwname, err);
return err;
}
@@ -2745,20 +2700,26 @@ static int btusb_intel_download_firmware(struct hci_dev *hdev,
goto done;
}
+ calltime = ktime_get();
+
set_bit(BTUSB_DOWNLOADING, &data->flags);
/* Start firmware downloading and get boot parameter */
- err = btintel_download_firmware(hdev, fw, boot_param);
+ err = btintel_download_firmware(hdev, ver, fw, boot_param);
if (err < 0) {
+ if (err == -EALREADY) {
+ /* Firmware has already been loaded */
+ set_bit(BTUSB_FIRMWARE_LOADED, &data->flags);
+ err = 0;
+ goto done;
+ }
+
/* When FW download fails, send Intel Reset to retry
* FW download.
*/
btintel_reset_to_bootloader(hdev);
goto done;
}
- set_bit(BTUSB_FIRMWARE_LOADED, &data->flags);
-
- bt_dev_info(hdev, "Waiting for firmware download to complete");
/* Before switching the device into operational mode and with that
* booting the loaded firmware, wait for the bootloader notification
@@ -2771,29 +2732,74 @@ static int btusb_intel_download_firmware(struct hci_dev *hdev,
* and thus just timeout if that happens and fail the setup
* of this device.
*/
- err = wait_on_bit_timeout(&data->flags, BTUSB_DOWNLOADING,
+ err = btusb_download_wait(hdev, calltime, 5000);
+ if (err == -ETIMEDOUT)
+ btintel_reset_to_bootloader(hdev);
+
+done:
+ release_firmware(fw);
+ return err;
+}
+
+static int btusb_boot_wait(struct hci_dev *hdev, ktime_t calltime, int msec)
+{
+ struct btusb_data *data = hci_get_drvdata(hdev);
+ ktime_t delta, rettime;
+ unsigned long long duration;
+ int err;
+
+ bt_dev_info(hdev, "Waiting for device to boot");
+
+ err = wait_on_bit_timeout(&data->flags, BTUSB_BOOTING,
TASK_INTERRUPTIBLE,
- msecs_to_jiffies(5000));
+ msecs_to_jiffies(msec));
if (err == -EINTR) {
- bt_dev_err(hdev, "Firmware loading interrupted");
- goto done;
+ bt_dev_err(hdev, "Device boot interrupted");
+ return -EINTR;
}
if (err) {
- bt_dev_err(hdev, "Firmware loading timeout");
- err = -ETIMEDOUT;
- btintel_reset_to_bootloader(hdev);
- goto done;
+ bt_dev_err(hdev, "Device boot timeout");
+ return -ETIMEDOUT;
}
- if (test_bit(BTUSB_FIRMWARE_FAILED, &data->flags)) {
- bt_dev_err(hdev, "Firmware loading failed");
- err = -ENOEXEC;
- goto done;
+ rettime = ktime_get();
+ delta = ktime_sub(rettime, calltime);
+ duration = (unsigned long long) ktime_to_ns(delta) >> 10;
+
+ bt_dev_info(hdev, "Device booted in %llu usecs", duration);
+
+ return 0;
+}
+
+static int btusb_intel_boot(struct hci_dev *hdev, u32 boot_addr)
+{
+ struct btusb_data *data = hci_get_drvdata(hdev);
+ ktime_t calltime;
+ int err;
+
+ calltime = ktime_get();
+
+ set_bit(BTUSB_BOOTING, &data->flags);
+
+ err = btintel_send_intel_reset(hdev, boot_addr);
+ if (err) {
+ bt_dev_err(hdev, "Intel Soft Reset failed (%d)", err);
+ btintel_reset_to_bootloader(hdev);
+ return err;
}
-done:
- release_firmware(fw);
+ /* The bootloader will not indicate when the device is ready. This
+ * is done by the operational firmware sending bootup notification.
+ *
+ * Booting into operational firmware should not take longer than
+ * 1 second. However if that happens, then just fail the setup
+ * since something went wrong.
+ */
+ err = btusb_boot_wait(hdev, calltime, 1000);
+ if (err == -ETIMEDOUT)
+ btintel_reset_to_bootloader(hdev);
+
return err;
}
@@ -2804,8 +2810,6 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
struct intel_boot_params params;
u32 boot_param;
char ddcname[64];
- ktime_t calltime, delta, rettime;
- unsigned long long duration;
int err;
struct intel_debug_features features;
@@ -2817,8 +2821,6 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
*/
boot_param = 0x00000000;
- calltime = ktime_get();
-
/* Read the Intel version information to determine if the device
* is in bootloader mode or if it already has operational firmware
* loaded.
@@ -2830,6 +2832,10 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
return err;
}
+ err = btintel_version_info(hdev, &ver);
+ if (err)
+ return err;
+
err = btusb_intel_download_firmware(hdev, &ver, &params, &boot_param);
if (err)
return err;
@@ -2838,59 +2844,16 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
if (ver.fw_variant == 0x23)
goto finish;
- rettime = ktime_get();
- delta = ktime_sub(rettime, calltime);
- duration = (unsigned long long) ktime_to_ns(delta) >> 10;
-
- bt_dev_info(hdev, "Firmware loaded in %llu usecs", duration);
-
- calltime = ktime_get();
-
- set_bit(BTUSB_BOOTING, &data->flags);
-
- err = btintel_send_intel_reset(hdev, boot_param);
- if (err) {
- bt_dev_err(hdev, "Intel Soft Reset failed (%d)", err);
- btintel_reset_to_bootloader(hdev);
+ err = btusb_intel_boot(hdev, boot_param);
+ if (err)
return err;
- }
-
- /* The bootloader will not indicate when the device is ready. This
- * is done by the operational firmware sending bootup notification.
- *
- * Booting into operational firmware should not take longer than
- * 1 second. However if that happens, then just fail the setup
- * since something went wrong.
- */
- bt_dev_info(hdev, "Waiting for device to boot");
-
- err = wait_on_bit_timeout(&data->flags, BTUSB_BOOTING,
- TASK_INTERRUPTIBLE,
- msecs_to_jiffies(1000));
-
- if (err == -EINTR) {
- bt_dev_err(hdev, "Device boot interrupted");
- return -EINTR;
- }
-
- if (err) {
- bt_dev_err(hdev, "Device boot timeout");
- btintel_reset_to_bootloader(hdev);
- return -ETIMEDOUT;
- }
-
- rettime = ktime_get();
- delta = ktime_sub(rettime, calltime);
- duration = (unsigned long long) ktime_to_ns(delta) >> 10;
-
- bt_dev_info(hdev, "Device booted in %llu usecs", duration);
clear_bit(BTUSB_BOOTLOADER, &data->flags);
err = btusb_setup_intel_new_get_fw_name(&ver, &params, ddcname,
sizeof(ddcname), "ddc");
- if (!err) {
+ if (err < 0) {
bt_dev_err(hdev, "Unsupported Intel firmware naming");
} else {
/* Once the device is running in operational mode, it needs to
@@ -2947,8 +2910,6 @@ static int btusb_setup_intel_newgen(struct hci_dev *hdev)
struct btusb_data *data = hci_get_drvdata(hdev);
u32 boot_param;
char ddcname[64];
- ktime_t calltime, delta, rettime;
- unsigned long long duration;
int err;
struct intel_debug_features features;
struct intel_version_tlv version;
@@ -2961,8 +2922,6 @@ static int btusb_setup_intel_newgen(struct hci_dev *hdev)
*/
boot_param = 0x00000000;
- calltime = ktime_get();
-
/* Read the Intel version information to determine if the device
* is in bootloader mode or if it already has operational firmware
* loaded.
@@ -2974,7 +2933,9 @@ static int btusb_setup_intel_newgen(struct hci_dev *hdev)
return err;
}
- btintel_version_info_tlv(hdev, &version);
+ err = btintel_version_info_tlv(hdev, &version);
+ if (err)
+ return err;
err = btusb_intel_download_firmware_newgen(hdev, &version, &boot_param);
if (err)
@@ -2984,52 +2945,9 @@ static int btusb_setup_intel_newgen(struct hci_dev *hdev)
if (version.img_type == 0x03)
goto finish;
- rettime = ktime_get();
- delta = ktime_sub(rettime, calltime);
- duration = (unsigned long long)ktime_to_ns(delta) >> 10;
-
- bt_dev_info(hdev, "Firmware loaded in %llu usecs", duration);
-
- calltime = ktime_get();
-
- set_bit(BTUSB_BOOTING, &data->flags);
-
- err = btintel_send_intel_reset(hdev, boot_param);
- if (err) {
- bt_dev_err(hdev, "Intel Soft Reset failed (%d)", err);
- btintel_reset_to_bootloader(hdev);
+ err = btusb_intel_boot(hdev, boot_param);
+ if (err)
return err;
- }
-
- /* The bootloader will not indicate when the device is ready. This
- * is done by the operational firmware sending bootup notification.
- *
- * Booting into operational firmware should not take longer than
- * 1 second. However if that happens, then just fail the setup
- * since something went wrong.
- */
- bt_dev_info(hdev, "Waiting for device to boot");
-
- err = wait_on_bit_timeout(&data->flags, BTUSB_BOOTING,
- TASK_INTERRUPTIBLE,
- msecs_to_jiffies(1000));
-
- if (err == -EINTR) {
- bt_dev_err(hdev, "Device boot interrupted");
- return -EINTR;
- }
-
- if (err) {
- bt_dev_err(hdev, "Device boot timeout");
- btintel_reset_to_bootloader(hdev);
- return -ETIMEDOUT;
- }
-
- rettime = ktime_get();
- delta = ktime_sub(rettime, calltime);
- duration = (unsigned long long)ktime_to_ns(delta) >> 10;
-
- bt_dev_info(hdev, "Device booted in %llu usecs", duration);
clear_bit(BTUSB_BOOTLOADER, &data->flags);
@@ -3495,7 +3413,7 @@ static int btusb_mtk_setup_firmware_79xx(struct hci_dev *hdev, const char *fwnam
fw_ptr = fw->data;
fw_bin_ptr = fw_ptr;
globaldesc = (struct btmtk_global_desc *)(fw_ptr + MTK_FW_ROM_PATCH_HEADER_SIZE);
- section_num = globaldesc->section_num;
+ section_num = le32_to_cpu(globaldesc->section_num);
for (i = 0; i < section_num; i++) {
first_block = 1;
@@ -3503,8 +3421,8 @@ static int btusb_mtk_setup_firmware_79xx(struct hci_dev *hdev, const char *fwnam
sectionmap = (struct btmtk_section_map *)(fw_ptr + MTK_FW_ROM_PATCH_HEADER_SIZE +
MTK_FW_ROM_PATCH_GD_SIZE + MTK_FW_ROM_PATCH_SEC_MAP_SIZE * i);
- section_offset = sectionmap->secoffset;
- dl_size = sectionmap->bin_info_spec.dlsize;
+ section_offset = le32_to_cpu(sectionmap->secoffset);
+ dl_size = le32_to_cpu(sectionmap->bin_info_spec.dlsize);
if (dl_size > 0) {
retry = 20;
@@ -3740,7 +3658,7 @@ static int btusb_mtk_setup(struct hci_dev *hdev)
int err, status;
u32 dev_id;
char fw_bin_name[64];
- u32 fw_version;
+ u32 fw_version = 0;
u8 param;
calltime = ktime_get();
diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c
index 3764ceb6fa0d..3cd57fc56ade 100644
--- a/drivers/bluetooth/hci_bcm.c
+++ b/drivers/bluetooth/hci_bcm.c
@@ -68,6 +68,8 @@ struct bcm_device_data {
* deassert = Bluetooth device may sleep when sleep criteria are met
* @shutdown: BT_REG_ON pin,
* power up or power down Bluetooth device internal regulators
+ * @reset: BT_RST_N pin,
+ * active low resets the Bluetooth logic core
* @set_device_wakeup: callback to toggle BT_WAKE pin
* either by accessing @device_wakeup or by calling @btlp
* @set_shutdown: callback to toggle BT_REG_ON pin
@@ -101,6 +103,7 @@ struct bcm_device {
const char *name;
struct gpio_desc *device_wakeup;
struct gpio_desc *shutdown;
+ struct gpio_desc *reset;
int (*set_device_wakeup)(struct bcm_device *, bool);
int (*set_shutdown)(struct bcm_device *, bool);
#ifdef CONFIG_ACPI
@@ -985,6 +988,15 @@ static int bcm_gpio_set_device_wakeup(struct bcm_device *dev, bool awake)
static int bcm_gpio_set_shutdown(struct bcm_device *dev, bool powered)
{
gpiod_set_value_cansleep(dev->shutdown, powered);
+ if (dev->reset)
+ /*
+ * The reset line is asserted on powerdown and deasserted
+ * on poweron so the inverse of powered is used. Notice
+ * that the GPIO line BT_RST_N needs to be specified as
+ * active low in the device tree or similar system
+ * description.
+ */
+ gpiod_set_value_cansleep(dev->reset, !powered);
return 0;
}
@@ -1050,6 +1062,11 @@ static int bcm_get_resources(struct bcm_device *dev)
if (IS_ERR(dev->shutdown))
return PTR_ERR(dev->shutdown);
+ dev->reset = devm_gpiod_get_optional(dev->dev, "reset",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(dev->reset))
+ return PTR_ERR(dev->reset);
+
dev->set_device_wakeup = bcm_gpio_set_device_wakeup;
dev->set_shutdown = bcm_gpio_set_shutdown;
@@ -1482,6 +1499,8 @@ static struct bcm_device_data bcm43438_device_data = {
static const struct of_device_id bcm_bluetooth_of_match[] = {
{ .compatible = "brcm,bcm20702a1" },
{ .compatible = "brcm,bcm4329-bt" },
+ { .compatible = "brcm,bcm4330-bt" },
+ { .compatible = "brcm,bcm4334-bt" },
{ .compatible = "brcm,bcm4345c5" },
{ .compatible = "brcm,bcm4330-bt" },
{ .compatible = "brcm,bcm43438-bt", .data = &bcm43438_device_data },
diff --git a/drivers/bluetooth/hci_intel.c b/drivers/bluetooth/hci_intel.c
index b20a40fab83e..7249b91d9b91 100644
--- a/drivers/bluetooth/hci_intel.c
+++ b/drivers/bluetooth/hci_intel.c
@@ -735,7 +735,7 @@ static int intel_setup(struct hci_uart *hu)
set_bit(STATE_DOWNLOADING, &intel->flags);
/* Start firmware downloading and get boot parameter */
- err = btintel_download_firmware(hdev, fw, &boot_param);
+ err = btintel_download_firmware(hdev, &ver, fw, &boot_param);
if (err < 0)
goto done;
@@ -784,7 +784,10 @@ static int intel_setup(struct hci_uart *hu)
done:
release_firmware(fw);
- if (err < 0)
+ /* Check if there was an error and if is not -EALREADY which means the
+ * firmware has already been loaded.
+ */
+ if (err < 0 && err != -EALREADY)
return err;
/* We need to restore the default speed before Intel reset */
diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
index de36af63e182..0a0056912d51 100644
--- a/drivers/bluetooth/hci_qca.c
+++ b/drivers/bluetooth/hci_qca.c
@@ -1066,7 +1066,7 @@ static void qca_controller_memdump(struct work_struct *work)
* packets in the buffer.
*/
/* For QCA6390, controller does not lost packets but
- * sequence number field of packat sometimes has error
+ * sequence number field of packet sometimes has error
* bits, so skip this checking for missing packet.
*/
while ((seq_no > qca_memdump->current_seq_no + 1) &&
@@ -1571,6 +1571,20 @@ static void qca_cmd_timeout(struct hci_dev *hdev)
mutex_unlock(&qca->hci_memdump_lock);
}
+static bool qca_prevent_wake(struct hci_dev *hdev)
+{
+ struct hci_uart *hu = hci_get_drvdata(hdev);
+ bool wakeup;
+
+ /* UART driver handles the interrupt from BT SoC.So we need to use
+ * device handle of UART driver to get the status of device may wakeup.
+ */
+ wakeup = device_may_wakeup(hu->serdev->ctrl->dev.parent);
+ bt_dev_dbg(hu->hdev, "wakeup status : %d", wakeup);
+
+ return !wakeup;
+}
+
static int qca_wcn3990_init(struct hci_uart *hu)
{
struct qca_serdev *qcadev;
@@ -1721,6 +1735,7 @@ retry:
qca_debugfs_init(hdev);
hu->hdev->hw_error = qca_hw_error;
hu->hdev->cmd_timeout = qca_cmd_timeout;
+ hu->hdev->prevent_wake = qca_prevent_wake;
} else if (ret == -ENOENT) {
/* No patch/nvm-config found, run with original fw/config */
set_bit(QCA_ROM_FW, &qca->flags);
diff --git a/drivers/bluetooth/virtio_bt.c b/drivers/bluetooth/virtio_bt.c
new file mode 100644
index 000000000000..c804db7e90f8
--- /dev/null
+++ b/drivers/bluetooth/virtio_bt.c
@@ -0,0 +1,401 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <linux/module.h>
+#include <linux/virtio.h>
+#include <linux/virtio_config.h>
+#include <linux/skbuff.h>
+
+#include <uapi/linux/virtio_ids.h>
+#include <uapi/linux/virtio_bt.h>
+
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
+
+#define VERSION "0.1"
+
+enum {
+ VIRTBT_VQ_TX,
+ VIRTBT_VQ_RX,
+ VIRTBT_NUM_VQS,
+};
+
+struct virtio_bluetooth {
+ struct virtio_device *vdev;
+ struct virtqueue *vqs[VIRTBT_NUM_VQS];
+ struct work_struct rx;
+ struct hci_dev *hdev;
+};
+
+static int virtbt_add_inbuf(struct virtio_bluetooth *vbt)
+{
+ struct virtqueue *vq = vbt->vqs[VIRTBT_VQ_RX];
+ struct scatterlist sg[1];
+ struct sk_buff *skb;
+ int err;
+
+ skb = alloc_skb(1000, GFP_KERNEL);
+ sg_init_one(sg, skb->data, 1000);
+
+ err = virtqueue_add_inbuf(vq, sg, 1, skb, GFP_KERNEL);
+ if (err < 0) {
+ kfree_skb(skb);
+ return err;
+ }
+
+ return 0;
+}
+
+static int virtbt_open(struct hci_dev *hdev)
+{
+ struct virtio_bluetooth *vbt = hci_get_drvdata(hdev);
+
+ if (virtbt_add_inbuf(vbt) < 0)
+ return -EIO;
+
+ virtqueue_kick(vbt->vqs[VIRTBT_VQ_RX]);
+ return 0;
+}
+
+static int virtbt_close(struct hci_dev *hdev)
+{
+ struct virtio_bluetooth *vbt = hci_get_drvdata(hdev);
+ int i;
+
+ cancel_work_sync(&vbt->rx);
+
+ for (i = 0; i < ARRAY_SIZE(vbt->vqs); i++) {
+ struct virtqueue *vq = vbt->vqs[i];
+ struct sk_buff *skb;
+
+ while ((skb = virtqueue_detach_unused_buf(vq)))
+ kfree_skb(skb);
+ }
+
+ return 0;
+}
+
+static int virtbt_flush(struct hci_dev *hdev)
+{
+ return 0;
+}
+
+static int virtbt_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ struct virtio_bluetooth *vbt = hci_get_drvdata(hdev);
+ struct scatterlist sg[1];
+ int err;
+
+ memcpy(skb_push(skb, 1), &hci_skb_pkt_type(skb), 1);
+
+ sg_init_one(sg, skb->data, skb->len);
+ err = virtqueue_add_outbuf(vbt->vqs[VIRTBT_VQ_TX], sg, 1, skb,
+ GFP_KERNEL);
+ if (err) {
+ kfree_skb(skb);
+ return err;
+ }
+
+ virtqueue_kick(vbt->vqs[VIRTBT_VQ_TX]);
+ return 0;
+}
+
+static int virtbt_setup_zephyr(struct hci_dev *hdev)
+{
+ struct sk_buff *skb;
+
+ /* Read Build Information */
+ skb = __hci_cmd_sync(hdev, 0xfc08, 0, NULL, HCI_INIT_TIMEOUT);
+ if (IS_ERR(skb))
+ return PTR_ERR(skb);
+
+ bt_dev_info(hdev, "%s", (char *)(skb->data + 1));
+
+ hci_set_fw_info(hdev, "%s", skb->data + 1);
+
+ kfree_skb(skb);
+ return 0;
+}
+
+static int virtbt_set_bdaddr_zephyr(struct hci_dev *hdev,
+ const bdaddr_t *bdaddr)
+{
+ struct sk_buff *skb;
+
+ /* Write BD_ADDR */
+ skb = __hci_cmd_sync(hdev, 0xfc06, 6, bdaddr, HCI_INIT_TIMEOUT);
+ if (IS_ERR(skb))
+ return PTR_ERR(skb);
+
+ kfree_skb(skb);
+ return 0;
+}
+
+static int virtbt_setup_intel(struct hci_dev *hdev)
+{
+ struct sk_buff *skb;
+
+ /* Intel Read Version */
+ skb = __hci_cmd_sync(hdev, 0xfc05, 0, NULL, HCI_CMD_TIMEOUT);
+ if (IS_ERR(skb))
+ return PTR_ERR(skb);
+
+ kfree_skb(skb);
+ return 0;
+}
+
+static int virtbt_set_bdaddr_intel(struct hci_dev *hdev, const bdaddr_t *bdaddr)
+{
+ struct sk_buff *skb;
+
+ /* Intel Write BD Address */
+ skb = __hci_cmd_sync(hdev, 0xfc31, 6, bdaddr, HCI_INIT_TIMEOUT);
+ if (IS_ERR(skb))
+ return PTR_ERR(skb);
+
+ kfree_skb(skb);
+ return 0;
+}
+
+static int virtbt_setup_realtek(struct hci_dev *hdev)
+{
+ struct sk_buff *skb;
+
+ /* Read ROM Version */
+ skb = __hci_cmd_sync(hdev, 0xfc6d, 0, NULL, HCI_INIT_TIMEOUT);
+ if (IS_ERR(skb))
+ return PTR_ERR(skb);
+
+ bt_dev_info(hdev, "ROM version %u", *((__u8 *) (skb->data + 1)));
+
+ kfree_skb(skb);
+ return 0;
+}
+
+static int virtbt_shutdown_generic(struct hci_dev *hdev)
+{
+ struct sk_buff *skb;
+
+ /* Reset */
+ skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT);
+ if (IS_ERR(skb))
+ return PTR_ERR(skb);
+
+ kfree_skb(skb);
+ return 0;
+}
+
+static void virtbt_rx_handle(struct virtio_bluetooth *vbt, struct sk_buff *skb)
+{
+ __u8 pkt_type;
+
+ pkt_type = *((__u8 *) skb->data);
+ skb_pull(skb, 1);
+
+ switch (pkt_type) {
+ case HCI_EVENT_PKT:
+ case HCI_ACLDATA_PKT:
+ case HCI_SCODATA_PKT:
+ case HCI_ISODATA_PKT:
+ hci_skb_pkt_type(skb) = pkt_type;
+ hci_recv_frame(vbt->hdev, skb);
+ break;
+ }
+}
+
+static void virtbt_rx_work(struct work_struct *work)
+{
+ struct virtio_bluetooth *vbt = container_of(work,
+ struct virtio_bluetooth, rx);
+ struct sk_buff *skb;
+ unsigned int len;
+
+ skb = virtqueue_get_buf(vbt->vqs[VIRTBT_VQ_RX], &len);
+ if (!skb)
+ return;
+
+ skb->len = len;
+ virtbt_rx_handle(vbt, skb);
+
+ if (virtbt_add_inbuf(vbt) < 0)
+ return;
+
+ virtqueue_kick(vbt->vqs[VIRTBT_VQ_RX]);
+}
+
+static void virtbt_tx_done(struct virtqueue *vq)
+{
+ struct sk_buff *skb;
+ unsigned int len;
+
+ while ((skb = virtqueue_get_buf(vq, &len)))
+ kfree_skb(skb);
+}
+
+static void virtbt_rx_done(struct virtqueue *vq)
+{
+ struct virtio_bluetooth *vbt = vq->vdev->priv;
+
+ schedule_work(&vbt->rx);
+}
+
+static int virtbt_probe(struct virtio_device *vdev)
+{
+ vq_callback_t *callbacks[VIRTBT_NUM_VQS] = {
+ [VIRTBT_VQ_TX] = virtbt_tx_done,
+ [VIRTBT_VQ_RX] = virtbt_rx_done,
+ };
+ const char *names[VIRTBT_NUM_VQS] = {
+ [VIRTBT_VQ_TX] = "tx",
+ [VIRTBT_VQ_RX] = "rx",
+ };
+ struct virtio_bluetooth *vbt;
+ struct hci_dev *hdev;
+ int err;
+ __u8 type;
+
+ if (!virtio_has_feature(vdev, VIRTIO_F_VERSION_1))
+ return -ENODEV;
+
+ type = virtio_cread8(vdev, offsetof(struct virtio_bt_config, type));
+
+ switch (type) {
+ case VIRTIO_BT_CONFIG_TYPE_PRIMARY:
+ case VIRTIO_BT_CONFIG_TYPE_AMP:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ vbt = kzalloc(sizeof(*vbt), GFP_KERNEL);
+ if (!vbt)
+ return -ENOMEM;
+
+ vdev->priv = vbt;
+ vbt->vdev = vdev;
+
+ INIT_WORK(&vbt->rx, virtbt_rx_work);
+
+ err = virtio_find_vqs(vdev, VIRTBT_NUM_VQS, vbt->vqs, callbacks,
+ names, NULL);
+ if (err)
+ return err;
+
+ hdev = hci_alloc_dev();
+ if (!hdev) {
+ err = -ENOMEM;
+ goto failed;
+ }
+
+ vbt->hdev = hdev;
+
+ hdev->bus = HCI_VIRTIO;
+ hdev->dev_type = type;
+ hci_set_drvdata(hdev, vbt);
+
+ hdev->open = virtbt_open;
+ hdev->close = virtbt_close;
+ hdev->flush = virtbt_flush;
+ hdev->send = virtbt_send_frame;
+
+ if (virtio_has_feature(vdev, VIRTIO_BT_F_VND_HCI)) {
+ __u16 vendor;
+
+ virtio_cread(vdev, struct virtio_bt_config, vendor, &vendor);
+
+ switch (vendor) {
+ case VIRTIO_BT_CONFIG_VENDOR_ZEPHYR:
+ hdev->manufacturer = 1521;
+ hdev->setup = virtbt_setup_zephyr;
+ hdev->shutdown = virtbt_shutdown_generic;
+ hdev->set_bdaddr = virtbt_set_bdaddr_zephyr;
+ break;
+
+ case VIRTIO_BT_CONFIG_VENDOR_INTEL:
+ hdev->manufacturer = 2;
+ hdev->setup = virtbt_setup_intel;
+ hdev->shutdown = virtbt_shutdown_generic;
+ hdev->set_bdaddr = virtbt_set_bdaddr_intel;
+ set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks);
+ set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);
+ set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks);
+ break;
+
+ case VIRTIO_BT_CONFIG_VENDOR_REALTEK:
+ hdev->manufacturer = 93;
+ hdev->setup = virtbt_setup_realtek;
+ hdev->shutdown = virtbt_shutdown_generic;
+ set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);
+ set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks);
+ break;
+ }
+ }
+
+ if (virtio_has_feature(vdev, VIRTIO_BT_F_MSFT_EXT)) {
+ __u16 msft_opcode;
+
+ virtio_cread(vdev, struct virtio_bt_config,
+ msft_opcode, &msft_opcode);
+
+ hci_set_msft_opcode(hdev, msft_opcode);
+ }
+
+ if (virtio_has_feature(vdev, VIRTIO_BT_F_AOSP_EXT))
+ hci_set_aosp_capable(hdev);
+
+ if (hci_register_dev(hdev) < 0) {
+ hci_free_dev(hdev);
+ err = -EBUSY;
+ goto failed;
+ }
+
+ return 0;
+
+failed:
+ vdev->config->del_vqs(vdev);
+ return err;
+}
+
+static void virtbt_remove(struct virtio_device *vdev)
+{
+ struct virtio_bluetooth *vbt = vdev->priv;
+ struct hci_dev *hdev = vbt->hdev;
+
+ hci_unregister_dev(hdev);
+ vdev->config->reset(vdev);
+
+ hci_free_dev(hdev);
+ vbt->hdev = NULL;
+
+ vdev->config->del_vqs(vdev);
+ kfree(vbt);
+}
+
+static struct virtio_device_id virtbt_table[] = {
+ { VIRTIO_ID_BT, VIRTIO_DEV_ANY_ID },
+ { 0 },
+};
+
+MODULE_DEVICE_TABLE(virtio, virtbt_table);
+
+static const unsigned int virtbt_features[] = {
+ VIRTIO_BT_F_VND_HCI,
+ VIRTIO_BT_F_MSFT_EXT,
+ VIRTIO_BT_F_AOSP_EXT,
+};
+
+static struct virtio_driver virtbt_driver = {
+ .driver.name = KBUILD_MODNAME,
+ .driver.owner = THIS_MODULE,
+ .feature_table = virtbt_features,
+ .feature_table_size = ARRAY_SIZE(virtbt_features),
+ .id_table = virtbt_table,
+ .probe = virtbt_probe,
+ .remove = virtbt_remove,
+};
+
+module_virtio_driver(virtbt_driver);
+
+MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
+MODULE_DESCRIPTION("Generic Bluetooth VIRTIO driver ver " VERSION);
+MODULE_VERSION(VERSION);
+MODULE_LICENSE("GPL");
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index ba2f439bc04d..ea4ae551c426 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -320,6 +320,7 @@ enum {
HCI_BREDR_ENABLED,
HCI_LE_SCAN_INTERRUPTED,
HCI_WIDEBAND_SPEECH_ENABLED,
+ HCI_EVENT_FILTER_CONFIGURED,
HCI_DUT_MODE,
HCI_VENDOR_DIAG,
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index ebdd4afe30d2..c73ac52af186 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -584,6 +584,11 @@ struct hci_dev {
#if IS_ENABLED(CONFIG_BT_MSFTEXT)
__u16 msft_opcode;
void *msft_data;
+ bool msft_curve_validity;
+#endif
+
+#if IS_ENABLED(CONFIG_BT_AOSPEXT)
+ bool aosp_capable;
#endif
int (*open)(struct hci_dev *hdev);
@@ -704,6 +709,7 @@ struct hci_chan {
struct sk_buff_head data_q;
unsigned int sent;
__u8 state;
+ bool amp;
};
struct hci_conn_params {
@@ -1238,6 +1244,13 @@ static inline void hci_set_msft_opcode(struct hci_dev *hdev, __u16 opcode)
#endif
}
+static inline void hci_set_aosp_capable(struct hci_dev *hdev)
+{
+#if IS_ENABLED(CONFIG_BT_AOSPEXT)
+ hdev->aosp_capable = true;
+#endif
+}
+
int hci_dev_open(__u16 dev);
int hci_dev_close(__u16 dev);
int hci_dev_do_close(struct hci_dev *hdev);
@@ -1742,8 +1755,8 @@ void hci_mgmt_chan_unregister(struct hci_mgmt_chan *c);
#define DISCOV_INTERLEAVED_INQUIRY_LEN 0x04
#define DISCOV_BREDR_INQUIRY_LEN 0x08
#define DISCOV_LE_RESTART_DELAY msecs_to_jiffies(200) /* msec */
-#define DISCOV_LE_FAST_ADV_INT_MIN 100 /* msec */
-#define DISCOV_LE_FAST_ADV_INT_MAX 150 /* msec */
+#define DISCOV_LE_FAST_ADV_INT_MIN 0x00A0 /* 100 msec */
+#define DISCOV_LE_FAST_ADV_INT_MAX 0x00F0 /* 150 msec */
void mgmt_fill_version_info(void *ver);
int mgmt_new_settings(struct hci_dev *hdev);
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 61800a7b6192..3c4f550e5a8b 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -494,6 +494,7 @@ struct l2cap_le_credits {
#define L2CAP_ECRED_MIN_MTU 64
#define L2CAP_ECRED_MIN_MPS 64
+#define L2CAP_ECRED_MAX_CID 5
struct l2cap_ecred_conn_req {
__le16 psm;
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index 839a2028009e..a7cffb069565 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -578,6 +578,7 @@ struct mgmt_rp_add_advertising {
#define MGMT_ADV_PARAM_TIMEOUT BIT(13)
#define MGMT_ADV_PARAM_INTERVALS BIT(14)
#define MGMT_ADV_PARAM_TX_POWER BIT(15)
+#define MGMT_ADV_PARAM_SCAN_RSP BIT(16)
#define MGMT_ADV_FLAG_SEC_MASK (MGMT_ADV_FLAG_SEC_1M | MGMT_ADV_FLAG_SEC_2M | \
MGMT_ADV_FLAG_SEC_CODED)
diff --git a/include/uapi/linux/virtio_bt.h b/include/uapi/linux/virtio_bt.h
new file mode 100644
index 000000000000..a7bd48daa9a9
--- /dev/null
+++ b/include/uapi/linux/virtio_bt.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+
+#ifndef _UAPI_LINUX_VIRTIO_BT_H
+#define _UAPI_LINUX_VIRTIO_BT_H
+
+#include <linux/virtio_types.h>
+
+/* Feature bits */
+#define VIRTIO_BT_F_VND_HCI 0 /* Indicates vendor command support */
+#define VIRTIO_BT_F_MSFT_EXT 1 /* Indicates MSFT vendor support */
+#define VIRTIO_BT_F_AOSP_EXT 2 /* Indicates AOSP vendor support */
+
+enum virtio_bt_config_type {
+ VIRTIO_BT_CONFIG_TYPE_PRIMARY = 0,
+ VIRTIO_BT_CONFIG_TYPE_AMP = 1,
+};
+
+enum virtio_bt_config_vendor {
+ VIRTIO_BT_CONFIG_VENDOR_NONE = 0,
+ VIRTIO_BT_CONFIG_VENDOR_ZEPHYR = 1,
+ VIRTIO_BT_CONFIG_VENDOR_INTEL = 2,
+ VIRTIO_BT_CONFIG_VENDOR_REALTEK = 3,
+};
+
+struct virtio_bt_config {
+ __u8 type;
+ __u16 vendor;
+ __u16 msft_opcode;
+} __attribute__((packed));
+
+#endif /* _UAPI_LINUX_VIRTIO_BT_H */
diff --git a/include/uapi/linux/virtio_ids.h b/include/uapi/linux/virtio_ids.h
index bc1c0621f5ed..b4f468e9441d 100644
--- a/include/uapi/linux/virtio_ids.h
+++ b/include/uapi/linux/virtio_ids.h
@@ -53,6 +53,7 @@
#define VIRTIO_ID_MEM 24 /* virtio mem */
#define VIRTIO_ID_FS 26 /* virtio filesystem */
#define VIRTIO_ID_PMEM 27 /* virtio pmem */
+#define VIRTIO_ID_BT 28 /* virtio bluetooth */
#define VIRTIO_ID_MAC80211_HWSIM 29 /* virtio mac80211-hwsim */
#endif /* _LINUX_VIRTIO_IDS_H */
diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
index cff4944d5b66..97617d02c8f9 100644
--- a/net/bluetooth/6lowpan.c
+++ b/net/bluetooth/6lowpan.c
@@ -205,8 +205,7 @@ static inline struct lowpan_peer *peer_lookup_dst(struct lowpan_btle_dev *dev,
}
}
- /* use the neighbour cache for matching addresses assigned by SLAAC
- */
+ /* use the neighbour cache for matching addresses assigned by SLAAC */
neigh = __ipv6_neigh_lookup(dev->netdev, nexthop);
if (neigh) {
list_for_each_entry_rcu(peer, &dev->peers, list) {
@@ -841,8 +840,6 @@ static void chan_close_cb(struct l2cap_chan *chan)
} else {
spin_unlock(&devices_lock);
}
-
- return;
}
static void chan_state_change_cb(struct l2cap_chan *chan, int state, int err)
diff --git a/net/bluetooth/Kconfig b/net/bluetooth/Kconfig
index 400c5130dc0a..e0ab4cd7afc3 100644
--- a/net/bluetooth/Kconfig
+++ b/net/bluetooth/Kconfig
@@ -99,6 +99,13 @@ config BT_MSFTEXT
This options enables support for the Microsoft defined HCI
vendor extensions.
+config BT_AOSPEXT
+ bool "Enable Android Open Source Project extensions"
+ depends on BT
+ help
+ This options enables support for the Android Open Source
+ Project defined HCI vendor extensions.
+
config BT_DEBUGFS
bool "Export Bluetooth internals in debugfs"
depends on BT && DEBUG_FS
diff --git a/net/bluetooth/Makefile b/net/bluetooth/Makefile
index 1c645fba8c49..cc0995301f93 100644
--- a/net/bluetooth/Makefile
+++ b/net/bluetooth/Makefile
@@ -20,5 +20,6 @@ bluetooth-$(CONFIG_BT_BREDR) += sco.o
bluetooth-$(CONFIG_BT_HS) += a2mp.o amp.o
bluetooth-$(CONFIG_BT_LEDS) += leds.o
bluetooth-$(CONFIG_BT_MSFTEXT) += msft.o
+bluetooth-$(CONFIG_BT_AOSPEXT) += aosp.o
bluetooth-$(CONFIG_BT_DEBUGFS) += hci_debugfs.o
bluetooth-$(CONFIG_BT_SELFTEST) += selftest.o
diff --git a/net/bluetooth/aosp.c b/net/bluetooth/aosp.c
new file mode 100644
index 000000000000..a1b7762335a5
--- /dev/null
+++ b/net/bluetooth/aosp.c
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2021 Intel Corporation
+ */
+
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
+
+#include "aosp.h"
+
+void aosp_do_open(struct hci_dev *hdev)
+{
+ struct sk_buff *skb;
+
+ if (!hdev->aosp_capable)
+ return;
+
+ bt_dev_dbg(hdev, "Initialize AOSP extension");
+
+ /* LE Get Vendor Capabilities Command */
+ skb = __hci_cmd_sync(hdev, hci_opcode_pack(0x3f, 0x153), 0, NULL,
+ HCI_CMD_TIMEOUT);
+ if (IS_ERR(skb))
+ return;
+
+ kfree_skb(skb);
+}
+
+void aosp_do_close(struct hci_dev *hdev)
+{
+ if (!hdev->aosp_capable)
+ return;
+
+ bt_dev_dbg(hdev, "Cleanup of AOSP extension");
+}
diff --git a/net/bluetooth/aosp.h b/net/bluetooth/aosp.h
new file mode 100644
index 000000000000..328fc6d39f70
--- /dev/null
+++ b/net/bluetooth/aosp.h
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2021 Intel Corporation
+ */
+
+#if IS_ENABLED(CONFIG_BT_AOSPEXT)
+
+void aosp_do_open(struct hci_dev *hdev);
+void aosp_do_close(struct hci_dev *hdev);
+
+#else
+
+static inline void aosp_do_open(struct hci_dev *hdev) {}
+static inline void aosp_do_close(struct hci_dev *hdev) {}
+
+#endif
diff --git a/net/bluetooth/ecdh_helper.h b/net/bluetooth/ecdh_helper.h
index a6f8d03d4aaf..830723971cf8 100644
--- a/net/bluetooth/ecdh_helper.h
+++ b/net/bluetooth/ecdh_helper.h
@@ -25,6 +25,6 @@
int compute_ecdh_secret(struct crypto_kpp *tfm, const u8 pair_public_key[64],
u8 secret[32]);
-int set_ecdh_privkey(struct crypto_kpp *tfm, const u8 *private_key);
+int set_ecdh_privkey(struct crypto_kpp *tfm, const u8 private_key[32]);
int generate_ecdh_public_key(struct crypto_kpp *tfm, u8 public_key[64]);
int generate_ecdh_keys(struct crypto_kpp *tfm, u8 public_key[64]);
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 6ffa89e3ba0a..88ec08978ff4 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -772,6 +772,16 @@ void hci_le_conn_failed(struct hci_conn *conn, u8 status)
hci_conn_del(conn);
+ /* The suspend notifier is waiting for all devices to disconnect and an
+ * LE connect cancel will result in an hci_le_conn_failed. Once the last
+ * connection is deleted, we should also wake the suspend queue to
+ * complete suspend operations.
+ */
+ if (list_empty(&hdev->conn_hash.list) &&
+ test_and_clear_bit(SUSPEND_DISCONNECTING, hdev->suspend_tasks)) {
+ wake_up(&hdev->suspend_wait_q);
+ }
+
/* Since we may have temporarily stopped the background scanning in
* favor of connection establishment, we should restart it.
*/
@@ -1830,8 +1840,6 @@ u32 hci_conn_get_phy(struct hci_conn *conn)
{
u32 phys = 0;
- hci_dev_lock(conn->hdev);
-
/* BLUETOOTH CORE SPECIFICATION Version 5.2 | Vol 2, Part B page 471:
* Table 6.2: Packets defined for synchronous, asynchronous, and
* CSB logical transport types.
@@ -1928,7 +1936,5 @@ u32 hci_conn_get_phy(struct hci_conn *conn)
break;
}
- hci_dev_unlock(conn->hdev);
-
return phys;
}
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index b0d9c36acc03..fd12f1652bdf 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -44,6 +44,7 @@
#include "smp.h"
#include "leds.h"
#include "msft.h"
+#include "aosp.h"
static void hci_rx_work(struct work_struct *work);
static void hci_cmd_work(struct work_struct *work);
@@ -1586,6 +1587,7 @@ setup_failed:
ret = hdev->set_diag(hdev, true);
msft_do_open(hdev);
+ aosp_do_open(hdev);
clear_bit(HCI_INIT, &hdev->flags);
@@ -1782,6 +1784,7 @@ int hci_dev_do_close(struct hci_dev *hdev)
hci_sock_dev_event(hdev, HCI_DEV_DOWN);
+ aosp_do_close(hdev);
msft_do_close(hdev);
if (hdev->flush)
@@ -3760,6 +3763,8 @@ struct hci_dev *hci_alloc_dev(void)
hdev->le_scan_window_suspend = 0x0012;
hdev->le_scan_int_discovery = DISCOV_LE_SCAN_INT;
hdev->le_scan_window_discovery = DISCOV_LE_SCAN_WIN;
+ hdev->le_scan_int_adv_monitor = 0x0060;
+ hdev->le_scan_window_adv_monitor = 0x0030;
hdev->le_scan_int_connect = 0x0060;
hdev->le_scan_window_connect = 0x0060;
hdev->le_conn_min_interval = 0x0018;
diff --git a/net/bluetooth/hci_debugfs.c b/net/bluetooth/hci_debugfs.c
index 1a0ab58bfad0..47f4f21fbc1a 100644
--- a/net/bluetooth/hci_debugfs.c
+++ b/net/bluetooth/hci_debugfs.c
@@ -274,7 +274,7 @@ static ssize_t use_debug_keys_read(struct file *file, char __user *user_buf,
struct hci_dev *hdev = file->private_data;
char buf[3];
- buf[0] = hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS) ? 'Y': 'N';
+ buf[0] = hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS) ? 'Y' : 'N';
buf[1] = '\n';
buf[2] = '\0';
return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
@@ -292,7 +292,7 @@ static ssize_t sc_only_mode_read(struct file *file, char __user *user_buf,
struct hci_dev *hdev = file->private_data;
char buf[3];
- buf[0] = hci_dev_test_flag(hdev, HCI_SC_ONLY) ? 'Y': 'N';
+ buf[0] = hci_dev_test_flag(hdev, HCI_SC_ONLY) ? 'Y' : 'N';
buf[1] = '\n';
buf[2] = '\0';
return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
@@ -428,7 +428,7 @@ static ssize_t ssp_debug_mode_read(struct file *file, char __user *user_buf,
struct hci_dev *hdev = file->private_data;
char buf[3];
- buf[0] = hdev->ssp_debug_mode ? 'Y': 'N';
+ buf[0] = hdev->ssp_debug_mode ? 'Y' : 'N';
buf[1] = '\n';
buf[2] = '\0';
return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
@@ -742,7 +742,7 @@ static ssize_t force_static_address_read(struct file *file,
struct hci_dev *hdev = file->private_data;
char buf[3];
- buf[0] = hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR) ? 'Y': 'N';
+ buf[0] = hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR) ? 'Y' : 'N';
buf[1] = '\n';
buf[2] = '\0';
return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 67668be3461e..016b2999f219 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -395,6 +395,29 @@ done:
hci_dev_unlock(hdev);
}
+static void hci_cc_set_event_filter(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ __u8 status = *((__u8 *)skb->data);
+ struct hci_cp_set_event_filter *cp;
+ void *sent;
+
+ BT_DBG("%s status 0x%2.2x", hdev->name, status);
+
+ if (status)
+ return;
+
+ sent = hci_sent_cmd_data(hdev, HCI_OP_SET_EVENT_FLT);
+ if (!sent)
+ return;
+
+ cp = (struct hci_cp_set_event_filter *)sent;
+
+ if (cp->flt_type == HCI_FLT_CLEAR_ALL)
+ hci_dev_clear_flag(hdev, HCI_EVENT_FILTER_CONFIGURED);
+ else
+ hci_dev_set_flag(hdev, HCI_EVENT_FILTER_CONFIGURED);
+}
+
static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
@@ -1189,12 +1212,11 @@ static void hci_cc_le_set_adv_set_random_addr(struct hci_dev *hdev,
hci_dev_lock(hdev);
- if (!hdev->cur_adv_instance) {
+ if (!cp->handle) {
/* Store in hdev for instance 0 (Set adv and Directed advs) */
bacpy(&hdev->random_addr, &cp->bdaddr);
} else {
- adv_instance = hci_find_adv_instance(hdev,
- hdev->cur_adv_instance);
+ adv_instance = hci_find_adv_instance(hdev, cp->handle);
if (adv_instance)
bacpy(&adv_instance->random_addr, &cp->bdaddr);
}
@@ -1755,17 +1777,16 @@ static void hci_cc_set_ext_adv_param(struct hci_dev *hdev, struct sk_buff *skb)
hci_dev_lock(hdev);
hdev->adv_addr_type = cp->own_addr_type;
- if (!hdev->cur_adv_instance) {
+ if (!cp->handle) {
/* Store in hdev for instance 0 */
hdev->adv_tx_power = rp->tx_power;
} else {
- adv_instance = hci_find_adv_instance(hdev,
- hdev->cur_adv_instance);
+ adv_instance = hci_find_adv_instance(hdev, cp->handle);
if (adv_instance)
adv_instance->tx_power = rp->tx_power;
}
/* Update adv data as tx power is known now */
- hci_req_update_adv_data(hdev, hdev->cur_adv_instance);
+ hci_req_update_adv_data(hdev, cp->handle);
hci_dev_unlock(hdev);
}
@@ -3328,6 +3349,10 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb,
hci_cc_write_scan_enable(hdev, skb);
break;
+ case HCI_OP_SET_EVENT_FLT:
+ hci_cc_set_event_filter(hdev, skb);
+ break;
+
case HCI_OP_READ_CLASS_OF_DEV:
hci_cc_read_class_of_dev(hdev, skb);
break;
@@ -5005,6 +5030,7 @@ static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
return;
hchan->handle = le16_to_cpu(ev->handle);
+ hchan->amp = true;
BT_DBG("hcon %p mgr %p hchan %p", hcon, hcon->amp_mgr, hchan);
@@ -5037,7 +5063,7 @@ static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev,
hci_dev_lock(hdev);
hchan = hci_chan_lookup_handle(hdev, le16_to_cpu(ev->handle));
- if (!hchan)
+ if (!hchan || !hchan->amp)
goto unlock;
amp_destroy_logical_link(hchan, ev->reason);
@@ -5280,12 +5306,12 @@ static void hci_le_ext_adv_term_evt(struct hci_dev *hdev, struct sk_buff *skb)
if (hdev->adv_addr_type != ADDR_LE_DEV_RANDOM)
return;
- if (!hdev->cur_adv_instance) {
+ if (!ev->handle) {
bacpy(&conn->resp_addr, &hdev->random_addr);
return;
}
- adv_instance = hci_find_adv_instance(hdev, hdev->cur_adv_instance);
+ adv_instance = hci_find_adv_instance(hdev, ev->handle);
if (adv_instance)
bacpy(&conn->resp_addr, &adv_instance->random_addr);
}
@@ -5863,7 +5889,7 @@ static void hci_le_remote_conn_param_req_evt(struct hci_dev *hdev,
params->conn_latency = latency;
params->supervision_timeout = timeout;
store_hint = 0x01;
- } else{
+ } else {
store_hint = 0x00;
}
@@ -5911,7 +5937,7 @@ static void hci_le_phy_update_evt(struct hci_dev *hdev, struct sk_buff *skb)
BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
- if (!ev->status)
+ if (ev->status)
return;
hci_dev_lock(hdev);
diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c
index e55976db4403..560b74d421a8 100644
--- a/net/bluetooth/hci_request.c
+++ b/net/bluetooth/hci_request.c
@@ -847,6 +847,10 @@ static u8 update_white_list(struct hci_request *req)
*/
bool allow_rpa = hdev->suspended;
+ if (use_ll_privacy(hdev) &&
+ hci_dev_test_flag(hdev, HCI_ENABLE_LL_PRIVACY))
+ allow_rpa = true;
+
/* Go through the current white list programmed into the
* controller one by one and check if that address is still
* in the list of pending connections or list of devices to
@@ -1131,14 +1135,14 @@ static void hci_req_clear_event_filter(struct hci_request *req)
{
struct hci_cp_set_event_filter f;
- memset(&f, 0, sizeof(f));
- f.flt_type = HCI_FLT_CLEAR_ALL;
- hci_req_add(req, HCI_OP_SET_EVENT_FLT, 1, &f);
+ if (!hci_dev_test_flag(req->hdev, HCI_BREDR_ENABLED))
+ return;
- /* Update page scan state (since we may have modified it when setting
- * the event filter).
- */
- __hci_req_update_scan(req);
+ if (hci_dev_test_flag(req->hdev, HCI_EVENT_FILTER_CONFIGURED)) {
+ memset(&f, 0, sizeof(f));
+ f.flt_type = HCI_FLT_CLEAR_ALL;
+ hci_req_add(req, HCI_OP_SET_EVENT_FLT, 1, &f);
+ }
}
static void hci_req_set_event_filter(struct hci_request *req)
@@ -1147,6 +1151,10 @@ static void hci_req_set_event_filter(struct hci_request *req)
struct hci_cp_set_event_filter f;
struct hci_dev *hdev = req->hdev;
u8 scan = SCAN_DISABLED;
+ bool scanning = test_bit(HCI_PSCAN, &hdev->flags);
+
+ if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
+ return;
/* Always clear event filter when starting */
hci_req_clear_event_filter(req);
@@ -1167,12 +1175,13 @@ static void hci_req_set_event_filter(struct hci_request *req)
scan = SCAN_PAGE;
}
- if (scan)
+ if (scan && !scanning) {
set_bit(SUSPEND_SCAN_ENABLE, hdev->suspend_tasks);
- else
+ hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
+ } else if (!scan && scanning) {
set_bit(SUSPEND_SCAN_DISABLE, hdev->suspend_tasks);
-
- hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
+ hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
+ }
}
static void cancel_adv_timeout(struct hci_dev *hdev)
@@ -1315,9 +1324,14 @@ void hci_req_prepare_suspend(struct hci_dev *hdev, enum suspended_state next)
hdev->advertising_paused = true;
hdev->advertising_old_state = old_state;
- /* Disable page scan */
- page_scan = SCAN_DISABLED;
- hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &page_scan);
+
+ /* Disable page scan if enabled */
+ if (test_bit(HCI_PSCAN, &hdev->flags)) {
+ page_scan = SCAN_DISABLED;
+ hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1,
+ &page_scan);
+ set_bit(SUSPEND_SCAN_DISABLE, hdev->suspend_tasks);
+ }
/* Disable LE passive scan if enabled */
if (hci_dev_test_flag(hdev, HCI_LE_SCAN)) {
@@ -1328,9 +1342,6 @@ void hci_req_prepare_suspend(struct hci_dev *hdev, enum suspended_state next)
/* Disable advertisement filters */
hci_req_add_set_adv_filter_enable(&req, false);
- /* Mark task needing completion */
- set_bit(SUSPEND_SCAN_DISABLE, hdev->suspend_tasks);
-
/* Prevent disconnects from causing scanning to be re-enabled */
hdev->scanning_paused = true;
@@ -1364,7 +1375,10 @@ void hci_req_prepare_suspend(struct hci_dev *hdev, enum suspended_state next)
hdev->suspended = false;
hdev->scanning_paused = false;
+ /* Clear any event filters and restore scan state */
hci_req_clear_event_filter(&req);
+ __hci_req_update_scan(&req);
+
/* Reset passive/background scanning to normal */
__hci_update_background_scan(&req);
/* Enable all of the advertisement filters */
@@ -1637,9 +1651,8 @@ static u8 create_default_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
{
u8 scan_rsp_len = 0;
- if (hdev->appearance) {
+ if (hdev->appearance)
scan_rsp_len = append_appearance(hdev, ptr, scan_rsp_len);
- }
return append_local_name(hdev, ptr, scan_rsp_len);
}
@@ -1657,9 +1670,8 @@ static u8 create_instance_scan_rsp_data(struct hci_dev *hdev, u8 instance,
instance_flags = adv_instance->flags;
- if ((instance_flags & MGMT_ADV_FLAG_APPEARANCE) && hdev->appearance) {
+ if ((instance_flags & MGMT_ADV_FLAG_APPEARANCE) && hdev->appearance)
scan_rsp_len = append_appearance(hdev, ptr, scan_rsp_len);
- }
memcpy(&ptr[scan_rsp_len], adv_instance->scan_rsp_data,
adv_instance->scan_rsp_len);
@@ -2035,7 +2047,8 @@ int hci_get_random_address(struct hci_dev *hdev, bool require_privacy,
/* If Controller supports LL Privacy use own address type is
* 0x03
*/
- if (use_ll_privacy(hdev))
+ if (use_ll_privacy(hdev) &&
+ hci_dev_test_flag(hdev, HCI_ENABLE_LL_PRIVACY))
*own_addr_type = ADDR_LE_DEV_RANDOM_RESOLVED;
else
*own_addr_type = ADDR_LE_DEV_RANDOM;
@@ -2170,7 +2183,8 @@ int __hci_req_setup_ext_adv_instance(struct hci_request *req, u8 instance)
cp.evt_properties = cpu_to_le16(LE_EXT_ADV_CONN_IND);
else
cp.evt_properties = cpu_to_le16(LE_LEGACY_ADV_IND);
- } else if (adv_instance_is_scannable(hdev, instance)) {
+ } else if (adv_instance_is_scannable(hdev, instance) ||
+ (flags & MGMT_ADV_PARAM_SCAN_RSP)) {
if (secondary_adv)
cp.evt_properties = cpu_to_le16(LE_EXT_ADV_SCAN_IND);
else
@@ -2508,7 +2522,8 @@ int hci_update_random_address(struct hci_request *req, bool require_privacy,
/* If Controller supports LL Privacy use own address type is
* 0x03
*/
- if (use_ll_privacy(hdev))
+ if (use_ll_privacy(hdev) &&
+ hci_dev_test_flag(hdev, HCI_ENABLE_LL_PRIVACY))
*own_addr_type = ADDR_LE_DEV_RANDOM_RESOLVED;
else
*own_addr_type = ADDR_LE_DEV_RANDOM;
@@ -2941,6 +2956,9 @@ static int bredr_inquiry(struct hci_request *req, unsigned long opt)
const u8 liac[3] = { 0x00, 0x8b, 0x9e };
struct hci_cp_inquiry cp;
+ if (test_bit(HCI_INQUIRY, &req->hdev->flags))
+ return 0;
+
bt_dev_dbg(req->hdev, "");
hci_dev_lock(req->hdev);
@@ -3241,6 +3259,7 @@ bool hci_req_stop_discovery(struct hci_request *req)
if (hci_dev_test_flag(hdev, HCI_LE_SCAN)) {
cancel_delayed_work(&hdev->le_scan_disable);
+ cancel_delayed_work(&hdev->le_scan_restart);
hci_req_add_le_scan_disable(req, false);
}
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 72c2f5226d67..b6a88b8256c7 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -451,6 +451,8 @@ struct l2cap_chan *l2cap_chan_create(void)
if (!chan)
return NULL;
+ skb_queue_head_init(&chan->tx_q);
+ skb_queue_head_init(&chan->srej_q);
mutex_init(&chan->lock);
/* Set default lock nesting level */
@@ -490,14 +492,14 @@ static void l2cap_chan_destroy(struct kref *kref)
void l2cap_chan_hold(struct l2cap_chan *c)
{
- BT_DBG("chan %p orig refcnt %d", c, kref_read(&c->kref));
+ BT_DBG("chan %p orig refcnt %u", c, kref_read(&c->kref));
kref_get(&c->kref);
}
void l2cap_chan_put(struct l2cap_chan *c)
{
- BT_DBG("chan %p orig refcnt %d", c, kref_read(&c->kref));
+ BT_DBG("chan %p orig refcnt %u", c, kref_read(&c->kref));
kref_put(&c->kref, l2cap_chan_destroy);
}
@@ -516,7 +518,9 @@ void l2cap_chan_set_defaults(struct l2cap_chan *chan)
chan->flush_to = L2CAP_DEFAULT_FLUSH_TO;
chan->retrans_timeout = L2CAP_DEFAULT_RETRANS_TO;
chan->monitor_timeout = L2CAP_DEFAULT_MONITOR_TO;
+
chan->conf_state = 0;
+ set_bit(CONF_NOT_COMPLETE, &chan->conf_state);
set_bit(FLAG_FORCE_ACTIVE, &chan->flags);
}
@@ -648,7 +652,7 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err)
if (test_bit(CONF_NOT_COMPLETE, &chan->conf_state))
return;
- switch(chan->mode) {
+ switch (chan->mode) {
case L2CAP_MODE_BASIC:
break;
@@ -672,8 +676,6 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err)
skb_queue_purge(&chan->tx_q);
break;
}
-
- return;
}
EXPORT_SYMBOL_GPL(l2cap_chan_del);
@@ -1690,7 +1692,7 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)
smp_conn_security(hcon, hcon->pending_sec_level);
/* For LE slave connections, make sure the connection interval
- * is in the range of the minium and maximum interval that has
+ * is in the range of the minimum and maximum interval that has
* been configured for this connection. If not, then trigger
* the connection update procedure.
*/
@@ -5921,7 +5923,7 @@ static inline int l2cap_ecred_conn_req(struct l2cap_conn *conn,
struct l2cap_ecred_conn_req *req = (void *) data;
struct {
struct l2cap_ecred_conn_rsp rsp;
- __le16 dcid[5];
+ __le16 dcid[L2CAP_ECRED_MAX_CID];
} __packed pdu;
struct l2cap_chan *chan, *pchan;
u16 mtu, mps;
@@ -5938,6 +5940,14 @@ static inline int l2cap_ecred_conn_req(struct l2cap_conn *conn,
goto response;
}
+ cmd_len -= sizeof(*req);
+ num_scid = cmd_len / sizeof(u16);
+
+ if (num_scid > ARRAY_SIZE(pdu.dcid)) {
+ result = L2CAP_CR_LE_INVALID_PARAMS;
+ goto response;
+ }
+
mtu = __le16_to_cpu(req->mtu);
mps = __le16_to_cpu(req->mps);
@@ -5970,8 +5980,6 @@ static inline int l2cap_ecred_conn_req(struct l2cap_conn *conn,
}
result = L2CAP_CR_LE_SUCCESS;
- cmd_len -= sizeof(*req);
- num_scid = cmd_len / sizeof(u16);
for (i = 0; i < num_scid; i++) {
u16 scid = __le16_to_cpu(req->scid[i]);
@@ -7253,7 +7261,7 @@ static int l2cap_stream_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
L2CAP_TXSEQ_EXPECTED) {
l2cap_pass_to_tx(chan, control);
- BT_DBG("buffer_seq %d->%d", chan->buffer_seq,
+ BT_DBG("buffer_seq %u->%u", chan->buffer_seq,
__next_seq(chan, chan->buffer_seq));
chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
@@ -7542,7 +7550,7 @@ static void l2cap_data_channel(struct l2cap_conn *conn, u16 cid,
BT_DBG("chan %p, len %d", chan, skb->len);
/* If we receive data on a fixed channel before the info req/rsp
- * procdure is done simply assume that the channel is supported
+ * procedure is done simply assume that the channel is supported
* and mark it as ready.
*/
if (chan->chan_type == L2CAP_CHAN_FIXED)
@@ -7762,7 +7770,8 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon)
return conn;
}
-static bool is_valid_psm(u16 psm, u8 dst_type) {
+static bool is_valid_psm(u16 psm, u8 dst_type)
+{
if (!psm)
return false;
@@ -8356,7 +8365,7 @@ void l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
if (!conn)
goto drop;
- BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
+ BT_DBG("conn %p len %u flags 0x%x", conn, skb->len, flags);
switch (flags) {
case ACL_START:
@@ -8386,10 +8395,10 @@ void l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
return;
}
- BT_DBG("Start: total len %d, frag len %d", len, skb->len);
+ BT_DBG("Start: total len %d, frag len %u", len, skb->len);
if (skb->len > len) {
- BT_ERR("Frame is too long (len %d, expected len %d)",
+ BT_ERR("Frame is too long (len %u, expected len %d)",
skb->len, len);
l2cap_conn_unreliable(conn, ECOMM);
goto drop;
@@ -8402,7 +8411,7 @@ void l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
break;
case ACL_CONT:
- BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
+ BT_DBG("Cont: frag len %u (expecting %u)", skb->len, conn->rx_len);
if (!conn->rx_skb) {
BT_ERR("Unexpected continuation frame (len %d)", skb->len);
@@ -8423,7 +8432,7 @@ void l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
}
if (skb->len > conn->rx_len) {
- BT_ERR("Fragment is too long (len %d, expected %d)",
+ BT_ERR("Fragment is too long (len %u, expected %u)",
skb->len, conn->rx_len);
l2cap_recv_reset(conn);
l2cap_conn_unreliable(conn, ECOMM);
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index f1b1edd0b697..c99d65ef13b1 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -179,9 +179,17 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr,
struct l2cap_chan *chan = l2cap_pi(sk)->chan;
struct sockaddr_l2 la;
int len, err = 0;
+ bool zapped;
BT_DBG("sk %p", sk);
+ lock_sock(sk);
+ zapped = sock_flag(sk, SOCK_ZAPPED);
+ release_sock(sk);
+
+ if (zapped)
+ return -EINVAL;
+
if (!addr || alen < offsetofend(struct sockaddr, sa_family) ||
addr->sa_family != AF_BLUETOOTH)
return -EINVAL;
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 74971b4bd457..f9be7f9084d6 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -40,7 +40,7 @@
#include "msft.h"
#define MGMT_VERSION 1
-#define MGMT_REVISION 19
+#define MGMT_REVISION 20
static const u16 mgmt_commands[] = {
MGMT_OP_READ_INDEX_LIST,
@@ -108,6 +108,8 @@ static const u16 mgmt_commands[] = {
MGMT_OP_START_LIMITED_DISCOVERY,
MGMT_OP_READ_EXT_INFO,
MGMT_OP_SET_APPEARANCE,
+ MGMT_OP_GET_PHY_CONFIGURATION,
+ MGMT_OP_SET_PHY_CONFIGURATION,
MGMT_OP_SET_BLOCKED_KEYS,
MGMT_OP_SET_WIDEBAND_SPEECH,
MGMT_OP_READ_CONTROLLER_CAP,
@@ -166,6 +168,8 @@ static const u16 mgmt_events[] = {
MGMT_EV_PHY_CONFIGURATION_CHANGED,
MGMT_EV_EXP_FEATURE_CHANGED,
MGMT_EV_DEVICE_FLAGS_CHANGED,
+ MGMT_EV_ADV_MONITOR_ADDED,
+ MGMT_EV_ADV_MONITOR_REMOVED,
MGMT_EV_CONTROLLER_SUSPEND,
MGMT_EV_CONTROLLER_RESUME,
};
@@ -196,8 +200,6 @@ static const u16 mgmt_untrusted_events[] = {
MGMT_EV_EXT_INDEX_REMOVED,
MGMT_EV_EXT_INFO_CHANGED,
MGMT_EV_EXP_FEATURE_CHANGED,
- MGMT_EV_ADV_MONITOR_ADDED,
- MGMT_EV_ADV_MONITOR_REMOVED,
};
#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
@@ -3728,8 +3730,11 @@ static int read_controller_cap(struct sock *sk, struct hci_dev *hdev,
/* When the Read Simple Pairing Options command is supported, then
* the remote public key validation is supported.
+ *
+ * Alternatively, when Microsoft extensions are available, they can
+ * indicate support for public key validation as well.
*/
- if (hdev->commands[41] & 0x08)
+ if ((hdev->commands[41] & 0x08) || msft_curve_validity(hdev))
flags |= 0x01; /* Remote public key validation (BR/EDR) */
flags |= 0x02; /* Remote public key validation (LE) */
@@ -3982,7 +3987,7 @@ static int set_exp_feature(struct sock *sk, struct hci_dev *hdev,
if (hdev_is_powered(hdev))
return mgmt_cmd_status(sk, hdev->id,
MGMT_OP_SET_EXP_FEATURE,
- MGMT_STATUS_NOT_POWERED);
+ MGMT_STATUS_REJECTED);
/* Parameters are limited to a single octet */
if (data_len != MGMT_SET_EXP_FEATURE_SIZE + 1)
@@ -7432,6 +7437,7 @@ static u32 get_supported_adv_flags(struct hci_dev *hdev)
flags |= MGMT_ADV_PARAM_TIMEOUT;
flags |= MGMT_ADV_PARAM_INTERVALS;
flags |= MGMT_ADV_PARAM_TX_POWER;
+ flags |= MGMT_ADV_PARAM_SCAN_RSP;
/* In extended adv TX_POWER returned from Set Adv Param
* will be always valid.
@@ -7475,7 +7481,7 @@ static int read_adv_features(struct sock *sk, struct hci_dev *hdev,
* advertising.
*/
if (hci_dev_test_flag(hdev, HCI_ENABLE_LL_PRIVACY))
- return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
+ return mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_ADV_FEATURES,
MGMT_STATUS_NOT_SUPPORTED);
hci_dev_lock(hdev);
@@ -7976,7 +7982,6 @@ static int add_ext_adv_params(struct sock *sk, struct hci_dev *hdev,
goto unlock;
}
- hdev->cur_adv_instance = cp->instance;
/* Submit request for advertising params if ext adv available */
if (ext_adv_capable(hdev)) {
hci_req_init(&req, hdev);
diff --git a/net/bluetooth/msft.c b/net/bluetooth/msft.c
index 47b104f318e9..e28f15439ce4 100644
--- a/net/bluetooth/msft.c
+++ b/net/bluetooth/msft.c
@@ -142,6 +142,9 @@ static bool read_supported_features(struct hci_dev *hdev,
msft->evt_prefix_len = rp->evt_prefix_len;
msft->features = __le64_to_cpu(rp->features);
+ if (msft->features & MSFT_FEATURE_MASK_CURVE_VALIDITY)
+ hdev->msft_curve_validity = true;
+
kfree_skb(skb);
return true;
@@ -605,3 +608,8 @@ int msft_set_filter_enable(struct hci_dev *hdev, bool enable)
return err;
}
+
+bool msft_curve_validity(struct hci_dev *hdev)
+{
+ return hdev->msft_curve_validity;
+}
diff --git a/net/bluetooth/msft.h b/net/bluetooth/msft.h
index 88ed613dfa08..6e56d94b88d8 100644
--- a/net/bluetooth/msft.h
+++ b/net/bluetooth/msft.h
@@ -22,6 +22,7 @@ int msft_remove_monitor(struct hci_dev *hdev, struct adv_monitor *monitor,
u16 handle);
void msft_req_add_set_filter_enable(struct hci_request *req, bool enable);
int msft_set_filter_enable(struct hci_dev *hdev, bool enable);
+bool msft_curve_validity(struct hci_dev *hdev);
#else
@@ -54,4 +55,9 @@ static inline int msft_set_filter_enable(struct hci_dev *hdev, bool enable)
return -EOPNOTSUPP;
}
+static inline bool msft_curve_validity(struct hci_dev *hdev)
+{
+ return false;
+}
+
#endif
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index 22a110f37abc..3bd41563f118 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -51,8 +51,8 @@ struct sco_conn {
unsigned int mtu;
};
-#define sco_conn_lock(c) spin_lock(&c->lock);
-#define sco_conn_unlock(c) spin_unlock(&c->lock);
+#define sco_conn_lock(c) spin_lock(&c->lock)
+#define sco_conn_unlock(c) spin_unlock(&c->lock)
static void sco_sock_close(struct sock *sk);
static void sco_sock_kill(struct sock *sk);
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index b0c1ee110eff..5c17acfb1645 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -54,7 +54,7 @@
#define SMP_ALLOW_CMD(smp, code) set_bit(code, &smp->allow_cmd)
/* Keys which are not distributed with Secure Connections */
-#define SMP_SC_NO_DIST (SMP_DIST_ENC_KEY | SMP_DIST_LINK_KEY);
+#define SMP_SC_NO_DIST (SMP_DIST_ENC_KEY | SMP_DIST_LINK_KEY)
#define SMP_TIMEOUT msecs_to_jiffies(30000)
@@ -398,7 +398,7 @@ static int smp_e(const u8 *k, u8 *r)
SMP_DBG("r %16phN", r);
- memzero_explicit(&ctx, sizeof (ctx));
+ memzero_explicit(&ctx, sizeof(ctx));
return err;
}
@@ -595,7 +595,7 @@ static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data)
if (!chan)
return;
- BT_DBG("code 0x%2.2x", code);
+ bt_dev_dbg(conn->hcon->hdev, "code 0x%2.2x", code);
iv[0].iov_base = &code;
iv[0].iov_len = 1;
@@ -859,7 +859,8 @@ static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth,
memset(smp->tk, 0, sizeof(smp->tk));
clear_bit(SMP_FLAG_TK_VALID, &smp->flags);
- BT_DBG("tk_request: auth:%d lcl:%d rem:%d", auth, local_io, remote_io);
+ bt_dev_dbg(hcon->hdev, "auth:%d lcl:%d rem:%d", auth, local_io,
+ remote_io);
/* If neither side wants MITM, either "just" confirm an incoming
* request or use just-works for outgoing ones. The JUST_CFM
@@ -924,7 +925,7 @@ static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth,
get_random_bytes(&passkey, sizeof(passkey));
passkey %= 1000000;
put_unaligned_le32(passkey, smp->tk);
- BT_DBG("PassKey: %d", passkey);
+ bt_dev_dbg(hcon->hdev, "PassKey: %d", passkey);
set_bit(SMP_FLAG_TK_VALID, &smp->flags);
}
@@ -949,7 +950,7 @@ static u8 smp_confirm(struct smp_chan *smp)
struct smp_cmd_pairing_confirm cp;
int ret;
- BT_DBG("conn %p", conn);
+ bt_dev_dbg(conn->hcon->hdev, "conn %p", conn);
ret = smp_c1(smp->tk, smp->prnd, smp->preq, smp->prsp,
conn->hcon->init_addr_type, &conn->hcon->init_addr,
@@ -977,7 +978,8 @@ static u8 smp_random(struct smp_chan *smp)
u8 confirm[16];
int ret;
- BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
+ bt_dev_dbg(conn->hcon->hdev, "conn %p %s", conn,
+ conn->hcon->out ? "master" : "slave");
ret = smp_c1(smp->tk, smp->rrnd, smp->preq, smp->prsp,
hcon->init_addr_type, &hcon->init_addr,
@@ -1236,7 +1238,7 @@ static void smp_distribute_keys(struct smp_chan *smp)
struct hci_dev *hdev = hcon->hdev;
__u8 *keydist;
- BT_DBG("conn %p", conn);
+ bt_dev_dbg(hdev, "conn %p", conn);
rsp = (void *) &smp->prsp[1];
@@ -1266,7 +1268,7 @@ static void smp_distribute_keys(struct smp_chan *smp)
*keydist &= ~SMP_SC_NO_DIST;
}
- BT_DBG("keydist 0x%x", *keydist);
+ bt_dev_dbg(hdev, "keydist 0x%x", *keydist);
if (*keydist & SMP_DIST_ENC_KEY) {
struct smp_cmd_encrypt_info enc;
@@ -1366,13 +1368,14 @@ static void smp_timeout(struct work_struct *work)
security_timer.work);
struct l2cap_conn *conn = smp->conn;
- BT_DBG("conn %p", conn);
+ bt_dev_dbg(conn->hcon->hdev, "conn %p", conn);
hci_disconnect(conn->hcon, HCI_ERROR_REMOTE_USER_TERM);
}
static struct smp_chan *smp_chan_create(struct l2cap_conn *conn)
{
+ struct hci_conn *hcon = conn->hcon;
struct l2cap_chan *chan = conn->smp;
struct smp_chan *smp;
@@ -1382,13 +1385,13 @@ static struct smp_chan *smp_chan_create(struct l2cap_conn *conn)
smp->tfm_cmac = crypto_alloc_shash("cmac(aes)", 0, 0);
if (IS_ERR(smp->tfm_cmac)) {
- BT_ERR("Unable to create CMAC crypto context");
+ bt_dev_err(hcon->hdev, "Unable to create CMAC crypto context");
goto zfree_smp;
}
smp->tfm_ecdh = crypto_alloc_kpp("ecdh", 0, 0);
if (IS_ERR(smp->tfm_ecdh)) {
- BT_ERR("Unable to create ECDH crypto context");
+ bt_dev_err(hcon->hdev, "Unable to create ECDH crypto context");
goto free_shash;
}
@@ -1399,7 +1402,7 @@ static struct smp_chan *smp_chan_create(struct l2cap_conn *conn)
INIT_DELAYED_WORK(&smp->security_timer, smp_timeout);
- hci_conn_hold(conn->hcon);
+ hci_conn_hold(hcon);
return smp;
@@ -1564,8 +1567,8 @@ static u8 sc_passkey_round(struct smp_chan *smp, u8 smp_op)
if (!hcon->out)
return 0;
- BT_DBG("%s Starting passkey round %u", hdev->name,
- smp->passkey_round + 1);
+ bt_dev_dbg(hdev, "Starting passkey round %u",
+ smp->passkey_round + 1);
SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM);
@@ -1625,11 +1628,11 @@ int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey)
u32 value;
int err;
- BT_DBG("");
-
if (!conn)
return -ENOTCONN;
+ bt_dev_dbg(conn->hcon->hdev, "");
+
chan = conn->smp;
if (!chan)
return -ENOTCONN;
@@ -1651,7 +1654,7 @@ int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey)
case MGMT_OP_USER_PASSKEY_REPLY:
value = le32_to_cpu(passkey);
memset(smp->tk, 0, sizeof(smp->tk));
- BT_DBG("PassKey: %d", value);
+ bt_dev_dbg(conn->hcon->hdev, "PassKey: %d", value);
put_unaligned_le32(value, smp->tk);
fallthrough;
case MGMT_OP_USER_CONFIRM_REPLY:
@@ -1733,7 +1736,7 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
u8 key_size, auth, sec_level;
int ret;
- BT_DBG("conn %p", conn);
+ bt_dev_dbg(hdev, "conn %p", conn);
if (skb->len < sizeof(*req))
return SMP_INVALID_PARAMS;
@@ -1887,7 +1890,7 @@ static u8 sc_send_public_key(struct smp_chan *smp)
}
if (hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS)) {
- BT_DBG("Using debug keys");
+ bt_dev_dbg(hdev, "Using debug keys");
if (set_ecdh_privkey(smp->tfm_ecdh, debug_sk))
return SMP_UNSPECIFIED;
memcpy(smp->local_pk, debug_pk, 64);
@@ -1924,7 +1927,7 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
u8 key_size, auth;
int ret;
- BT_DBG("conn %p", conn);
+ bt_dev_dbg(hdev, "conn %p", conn);
if (skb->len < sizeof(*rsp))
return SMP_INVALID_PARAMS;
@@ -2019,7 +2022,7 @@ static u8 sc_check_confirm(struct smp_chan *smp)
{
struct l2cap_conn *conn = smp->conn;
- BT_DBG("");
+ bt_dev_dbg(conn->hcon->hdev, "");
if (smp->method == REQ_PASSKEY || smp->method == DSP_PASSKEY)
return sc_passkey_round(smp, SMP_CMD_PAIRING_CONFIRM);
@@ -2078,8 +2081,10 @@ static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
{
struct l2cap_chan *chan = conn->smp;
struct smp_chan *smp = chan->data;
+ struct hci_conn *hcon = conn->hcon;
+ struct hci_dev *hdev = hcon->hdev;
- BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
+ bt_dev_dbg(hdev, "conn %p %s", conn, hcon->out ? "master" : "slave");
if (skb->len < sizeof(smp->pcnf))
return SMP_INVALID_PARAMS;
@@ -2094,7 +2099,7 @@ static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
if (test_bit(SMP_FLAG_REMOTE_PK, &smp->flags))
return sc_check_confirm(smp);
- BT_ERR("Unexpected SMP Pairing Confirm");
+ bt_dev_err(hdev, "Unexpected SMP Pairing Confirm");
ret = fixup_sc_false_positive(smp);
if (ret)
@@ -2125,7 +2130,7 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
u32 passkey;
int err;
- BT_DBG("conn %p", conn);
+ bt_dev_dbg(hcon->hdev, "conn %p", conn);
if (skb->len < sizeof(smp->rrnd))
return SMP_INVALID_PARAMS;
@@ -2284,7 +2289,7 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
struct smp_chan *smp;
u8 sec_level, auth;
- BT_DBG("conn %p", conn);
+ bt_dev_dbg(hdev, "conn %p", conn);
if (skb->len < sizeof(*rp))
return SMP_INVALID_PARAMS;
@@ -2347,7 +2352,8 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
__u8 authreq;
int ret;
- BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);
+ bt_dev_dbg(hcon->hdev, "conn %p hcon %p level 0x%2.2x", conn, hcon,
+ sec_level);
/* This may be NULL if there's an unexpected disconnection */
if (!conn)
@@ -2483,7 +2489,7 @@ static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
struct l2cap_chan *chan = conn->smp;
struct smp_chan *smp = chan->data;
- BT_DBG("conn %p", conn);
+ bt_dev_dbg(conn->hcon->hdev, "conn %p", conn);
if (skb->len < sizeof(*rp))
return SMP_INVALID_PARAMS;
@@ -2516,7 +2522,7 @@ static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
struct smp_ltk *ltk;
u8 authenticated;
- BT_DBG("conn %p", conn);
+ bt_dev_dbg(hdev, "conn %p", conn);
if (skb->len < sizeof(*rp))
return SMP_INVALID_PARAMS;
@@ -2548,7 +2554,7 @@ static int smp_cmd_ident_info(struct l2cap_conn *conn, struct sk_buff *skb)
struct l2cap_chan *chan = conn->smp;
struct smp_chan *smp = chan->data;
- BT_DBG("");
+ bt_dev_dbg(conn->hcon->hdev, "");
if (skb->len < sizeof(*info))
return SMP_INVALID_PARAMS;
@@ -2580,7 +2586,7 @@ static int smp_cmd_ident_addr_info(struct l2cap_conn *conn,
struct hci_conn *hcon = conn->hcon;
bdaddr_t rpa;
- BT_DBG("");
+ bt_dev_dbg(hcon->hdev, "");
if (skb->len < sizeof(*info))
return SMP_INVALID_PARAMS;
@@ -2647,7 +2653,7 @@ static int smp_cmd_sign_info(struct l2cap_conn *conn, struct sk_buff *skb)
struct smp_chan *smp = chan->data;
struct smp_csrk *csrk;
- BT_DBG("conn %p", conn);
+ bt_dev_dbg(conn->hcon->hdev, "conn %p", conn);
if (skb->len < sizeof(*rp))
return SMP_INVALID_PARAMS;
@@ -2727,11 +2733,20 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb)
struct smp_cmd_pairing_confirm cfm;
int err;
- BT_DBG("conn %p", conn);
+ bt_dev_dbg(hdev, "conn %p", conn);
if (skb->len < sizeof(*key))
return SMP_INVALID_PARAMS;
+ /* Check if remote and local public keys are the same and debug key is
+ * not in use.
+ */
+ if (!test_bit(SMP_FLAG_DEBUG_KEY, &smp->flags) &&
+ !crypto_memneq(key, smp->local_pk, 64)) {
+ bt_dev_err(hdev, "Remote and local public keys are identical");
+ return SMP_UNSPECIFIED;
+ }
+
memcpy(smp->remote_pk, key, 64);
if (test_bit(SMP_FLAG_REMOTE_OOB, &smp->flags)) {
@@ -2782,7 +2797,7 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb)
smp->method = sc_select_method(smp);
- BT_DBG("%s selected method 0x%02x", hdev->name, smp->method);
+ bt_dev_dbg(hdev, "selected method 0x%02x", smp->method);
/* JUST_WORKS and JUST_CFM result in an unauthenticated key */
if (smp->method == JUST_WORKS || smp->method == JUST_CFM)
@@ -2857,7 +2872,7 @@ static int smp_cmd_dhkey_check(struct l2cap_conn *conn, struct sk_buff *skb)
u8 io_cap[3], r[16], e[16];
int err;
- BT_DBG("conn %p", conn);
+ bt_dev_dbg(hcon->hdev, "conn %p", conn);
if (skb->len < sizeof(*check))
return SMP_INVALID_PARAMS;
@@ -2917,7 +2932,7 @@ static int smp_cmd_keypress_notify(struct l2cap_conn *conn,
{
struct smp_cmd_keypress_notify *kp = (void *) skb->data;
- BT_DBG("value 0x%02x", kp->value);
+ bt_dev_dbg(conn->hcon->hdev, "value 0x%02x", kp->value);
return 0;
}
@@ -3014,7 +3029,7 @@ static int smp_sig_channel(struct l2cap_chan *chan, struct sk_buff *skb)
break;
default:
- BT_DBG("Unknown command code 0x%2.2x", code);
+ bt_dev_dbg(hcon->hdev, "Unknown command code 0x%2.2x", code);
reason = SMP_CMD_NOTSUPP;
goto done;
}
@@ -3039,7 +3054,7 @@ static void smp_teardown_cb(struct l2cap_chan *chan, int err)
{
struct l2cap_conn *conn = chan->conn;
- BT_DBG("chan %p", chan);
+ bt_dev_dbg(conn->hcon->hdev, "chan %p", chan);
if (chan->data)
smp_chan_destroy(conn);
@@ -3056,7 +3071,7 @@ static void bredr_pairing(struct l2cap_chan *chan)
struct smp_cmd_pairing req;
struct smp_chan *smp;
- BT_DBG("chan %p", chan);
+ bt_dev_dbg(hdev, "chan %p", chan);
/* Only new pairings are interesting */
if (!test_bit(HCI_CONN_NEW_LINK_KEY, &hcon->flags))
@@ -3103,7 +3118,7 @@ static void bredr_pairing(struct l2cap_chan *chan)
set_bit(SMP_FLAG_SC, &smp->flags);
- BT_DBG("%s starting SMP over BR/EDR", hdev->name);
+ bt_dev_dbg(hdev, "starting SMP over BR/EDR");
/* Prepare and send the BR/EDR SMP Pairing Request */
build_bredr_pairing_cmd(smp, &req, NULL);
@@ -3121,7 +3136,7 @@ static void smp_resume_cb(struct l2cap_chan *chan)
struct l2cap_conn *conn = chan->conn;
struct hci_conn *hcon = conn->hcon;
- BT_DBG("chan %p", chan);
+ bt_dev_dbg(hcon->hdev, "chan %p", chan);
if (hcon->type == ACL_LINK) {
bredr_pairing(chan);
@@ -3144,7 +3159,7 @@ static void smp_ready_cb(struct l2cap_chan *chan)
struct l2cap_conn *conn = chan->conn;
struct hci_conn *hcon = conn->hcon;
- BT_DBG("chan %p", chan);
+ bt_dev_dbg(hcon->hdev, "chan %p", chan);
/* No need to call l2cap_chan_hold() here since we already own
* the reference taken in smp_new_conn_cb(). This is just the
@@ -3162,7 +3177,7 @@ static int smp_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb)
{
int err;
- BT_DBG("chan %p", chan);
+ bt_dev_dbg(chan->conn->hcon->hdev, "chan %p", chan);
err = smp_sig_channel(chan, skb);
if (err) {
@@ -3214,7 +3229,7 @@ static inline struct l2cap_chan *smp_new_conn_cb(struct l2cap_chan *pchan)
{
struct l2cap_chan *chan;
- BT_DBG("pchan %p", pchan);
+ bt_dev_dbg(pchan->conn->hcon->hdev, "pchan %p", pchan);
chan = l2cap_chan_create();
if (!chan)
@@ -3235,7 +3250,7 @@ static inline struct l2cap_chan *smp_new_conn_cb(struct l2cap_chan *pchan)
*/
atomic_set(&chan->nesting, L2CAP_NESTING_SMP);
- BT_DBG("created chan %p", chan);
+ bt_dev_dbg(pchan->conn->hcon->hdev, "created chan %p", chan);
return chan;
}
@@ -3276,14 +3291,14 @@ static struct l2cap_chan *smp_add_cid(struct hci_dev *hdev, u16 cid)
tfm_cmac = crypto_alloc_shash("cmac(aes)", 0, 0);
if (IS_ERR(tfm_cmac)) {
- BT_ERR("Unable to create CMAC crypto context");
+ bt_dev_err(hdev, "Unable to create CMAC crypto context");
kfree_sensitive(smp);
return ERR_CAST(tfm_cmac);
}
tfm_ecdh = crypto_alloc_kpp("ecdh", 0, 0);
if (IS_ERR(tfm_ecdh)) {
- BT_ERR("Unable to create ECDH crypto context");
+ bt_dev_err(hdev, "Unable to create ECDH crypto context");
crypto_free_shash(tfm_cmac);
kfree_sensitive(smp);
return ERR_CAST(tfm_ecdh);
@@ -3339,7 +3354,7 @@ static void smp_del_chan(struct l2cap_chan *chan)
{
struct smp_dev *smp;
- BT_DBG("chan %p", chan);
+ bt_dev_dbg(chan->conn->hcon->hdev, "chan %p", chan);
smp = chan->data;
if (smp) {
@@ -3382,7 +3397,7 @@ int smp_register(struct hci_dev *hdev)
{
struct l2cap_chan *chan;
- BT_DBG("%s", hdev->name);
+ bt_dev_dbg(hdev, "");
/* If the controller does not support Low Energy operation, then
* there is also no need to register any SMP channel.