bluetooth-next pull request for net-next:

core:
  - L2CAP: Add support for setting BT_PHY
  - HCI: Add LE Channel Sounding HCI Command/event structures
  - hci_conn: Set link_policy on incoming ACL connections
  - MGMT: Add idle_timeout to configurable system parameters
 
 drivers:
  - btusb: Add support for MediaTek7920 0489:e158
  - btusb: Add device ID for Realtek RTL8761BU
  - btusb: Reject autosuspend if discovery is active
  - btusb: Add new VID/PID for RTL8852CE
  - btusb: Add USB ID 0489:e112 for Realtek 8851BE
  - dt-bindings: qcom: Split to separate schema
  - btqca: Add WCN6855 firmware priority selection feature
 -----BEGIN PGP SIGNATURE-----
 
 iQJNBAABCgA3FiEE7E6oRXp8w05ovYr/9JCA4xAyCykFAml7xEwZHGx1aXoudm9u
 LmRlbnR6QGludGVsLmNvbQAKCRD0kIDjEDILKZAnEACBXUlzYey49zIwVh/nExcS
 0HD1qDl7i6RpgeDeTGbGNiHk5IiS79GJbFar7KbxdbWHozPos21kAu0tZxDsC2w+
 KahxU1n3xHucO3YlXJh05W1SM3FLcHKM6o6Ib1+oycNAbWvfPMaYcG+vM34PBncM
 qoTeb8U8f3nI6P92SSJxIr1Dnj4pzOuNifWZoPP/51jRHeZdqICdFSvrK9OsgQZi
 dVyg+NIVgJav2q8BwnU8TAN6dmES9fnMEP8RDKDXH5IyKNG5eUdUEbceVj51+IUj
 t7B7XyPmYhIR37CKidxKh09HXNSZ+IGKiIX3c9Jl0PoUKzyisiXp6tQxcp0Vo54+
 IU9kZTMrI3MsWFh42PcHy1WBmBUxoHuy0y0+dMQ6xD1vOKI2z6yt07gxd4LIRZgZ
 QTwrUExrteobnxhqWjiDrtLf4ZqRg57Vgyu4Y0klf60MaHFiKoxVOLT9OCZ0mxsA
 fgoonLSvBJtRhl7lEUO/+p1enDvywVeZD9ygPFFuDSbM1TCOL116BVk5sHWZdQjD
 K5i2zr80b4YYiMrkX+7bHbxgX/aEVeMQHFkyvSutrqQql8oCmsqB4rIx0LKPtZX+
 lbixt6dR7MeCmcRgtPEmKUbG3vnt+1+NYziuAc1PtqvSxv4vfYjUOP/yZ0dpmsGk
 RPEObC9dq1rv564g586Dvw==
 =I+rw
 -----END PGP SIGNATURE-----

Merge tag 'for-net-next-2026-01-29' 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:

core:
 - L2CAP: Add support for setting BT_PHY
 - HCI: Add LE Channel Sounding HCI Command/event structures
 - hci_conn: Set link_policy on incoming ACL connections
 - MGMT: Add idle_timeout to configurable system parameters

drivers:
 - btusb: Add support for MediaTek7920 0489:e158
 - btusb: Add device ID for Realtek RTL8761BU
 - btusb: Reject autosuspend if discovery is active
 - btusb: Add new VID/PID for RTL8852CE
 - btusb: Add USB ID 0489:e112 for Realtek 8851BE
 - dt-bindings: qcom: Split to separate schema
 - btqca: Add WCN6855 firmware priority selection feature

* tag 'for-net-next-2026-01-29' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next: (40 commits)
  Bluetooth: hci_qca: Enable HFP hardware offload for WCN6855 and WCN7850
  Bluetooth: hci_qca: Refactor HFP hardware offload capability handling
  Bluetooth: btusb: Add USB ID 7392:e611 for Edimax EW-7611UXB
  Bluetooth: L2CAP: Fix not tracking outstanding TX ident
  Bluetooth: MGMT: Fix memory leak in set_ssp_complete
  Bluetooth: hci_uart: fix null-ptr-deref in hci_uart_write_work
  Bluetooth: btusb: Remove duplicate entry for 0x13d3/0x3618
  Bluetooth: btusb: Add device ID for Realtek RTL8761BU
  Bluetooth: btintel: Remove unneeded CONFIG_PM* #ifdef's
  Bluetooth: btnxpuart: Remove unneeded CONFIG_PM ifdef
  Bluetooth: btusb: Add new VID/PID for RTL8852CE
  Bluetooth: btintel_pcie: Remove unnecessary check before kfree_skb()
  Bluetooth: btusb: Reject autosuspend if discovery is active
  Bluetooth: hci_core: Export hci_discovery_active
  Bluetooth: btusb: Use pm_ptr instead of #ifdef CONFIG_PM
  dt-bindings: bluetooth: qcom,wcn7850-bt: Deprecate old supplies
  dt-bindings: bluetooth: qcom,wcn7850-bt: Split to separate schema
  dt-bindings: bluetooth: qcom,wcn6855-bt: Deprecate old supplies
  dt-bindings: bluetooth: qcom,wcn6855-bt: Split to separate schema
  dt-bindings: bluetooth: qcom,wcn6750-bt: Deprecate old supplies
  ...
====================

Link: https://patch.msgid.link/20260129203610.963067-1-luiz.dentz@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski 2026-01-29 17:22:35 -08:00
commit 7227e984c3
34 changed files with 1503 additions and 413 deletions

View File

@ -0,0 +1,25 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/net/bluetooth/qcom,bluetooth-common.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Bluetooth Common Properties
maintainers:
- Balakrishna Godavarthi <quic_bgodavar@quicinc.com>
- Rocky Liao <quic_rjliao@quicinc.com>
properties:
firmware-name:
minItems: 1
items:
- description: specify the name of nvm firmware to load
- description: specify the name of rampatch firmware to load
qcom,local-bd-address-broken:
type: boolean
description:
boot firmware is incorrectly passing the address in big-endian order
additionalProperties: true

View File

@ -0,0 +1,49 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/net/bluetooth/qcom,qca2066-bt.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm QCA2006 Bluetooth
maintainers:
- Balakrishna Godavarthi <quic_bgodavar@quicinc.com>
- Rocky Liao <quic_rjliao@quicinc.com>
properties:
compatible:
enum:
- qcom,qca2066-bt
- qcom,qca6174-bt
clocks:
items:
- description: External low-power 32.768 kHz clock input
enable-gpios:
maxItems: 1
required:
- compatible
- clocks
- enable-gpios
allOf:
- $ref: bluetooth-controller.yaml#
- $ref: qcom,bluetooth-common.yaml
- $ref: /schemas/serial/serial-peripheral-props.yaml#
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
serial {
bluetooth {
compatible = "qcom,qca6174-bt";
clocks = <&divclk4>;
enable-gpios = <&pm8994_gpios 19 GPIO_ACTIVE_HIGH>;
firmware-name = "nvm_00440302.bin";
};
};

View File

@ -0,0 +1,64 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/net/bluetooth/qcom,qca6390-bt.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm QCA6390 Bluetooth
maintainers:
- Balakrishna Godavarthi <quic_bgodavar@quicinc.com>
- Rocky Liao <quic_rjliao@quicinc.com>
properties:
compatible:
enum:
- qcom,qca6390-bt
vddaon-supply:
description: VDD_AON supply regulator handle
vddbtcmx-supply:
description: VDD_BT_CMX supply regulator handle
vddrfa0p8-supply:
description: VDD_RFA_0P8 supply regulator handle
vddrfa1p2-supply:
description: VDD_RFA_1P2 supply regulator handle
vddrfa1p7-supply:
description: VDD_RFA_1P7 supply regulator handle
vddrfacmn-supply:
description: VDD_RFA_CMN supply regulator handle
required:
- compatible
- vddaon-supply
- vddbtcmx-supply
- vddrfa0p8-supply
- vddrfa1p2-supply
- vddrfa1p7-supply
- vddrfacmn-supply
allOf:
- $ref: bluetooth-controller.yaml#
- $ref: qcom,bluetooth-common.yaml
- $ref: /schemas/serial/serial-peripheral-props.yaml#
unevaluatedProperties: false
examples:
- |
serial {
bluetooth {
compatible = "qcom,qca6390-bt";
vddaon-supply = <&vreg_pmu_aon_0p59>;
vddbtcmx-supply = <&vreg_pmu_btcmx_0p85>;
vddrfa0p8-supply = <&vreg_pmu_rfa_0p8>;
vddrfa1p2-supply = <&vreg_pmu_rfa_1p2>;
vddrfa1p7-supply = <&vreg_pmu_rfa_1p7>;
vddrfacmn-supply = <&vreg_pmu_rfa_cmn>;
};
};

View File

@ -0,0 +1,58 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/net/bluetooth/qcom,qca9377-bt.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm QCA9377 Bluetooth
maintainers:
- Balakrishna Godavarthi <quic_bgodavar@quicinc.com>
- Rocky Liao <quic_rjliao@quicinc.com>
properties:
compatible:
enum:
- qcom,qca9377-bt
clocks:
items:
- description: External low-power 32.768 kHz clock input
enable-gpios:
maxItems: 1
vddio-supply:
description: VDD_IO supply regulator handle
vddxo-supply:
description: VDD_XO supply regulator handle
required:
- compatible
- clocks
- enable-gpios
allOf:
- $ref: bluetooth-controller.yaml#
- $ref: qcom,bluetooth-common.yaml
- $ref: /schemas/serial/serial-peripheral-props.yaml#
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
serial {
bluetooth {
compatible = "qcom,qca9377-bt";
clocks = <&rk809 1>;
enable-gpios = <&gpio3 5 GPIO_ACTIVE_HIGH>;
max-speed = <2000000>;
pinctrl-names = "default";
pinctrl-0 = <&bt_enable>;
vddio-supply = <&vcc_1v8>;
vddxo-supply = <&vcc3v3_sys>;
};
};

View File

@ -0,0 +1,67 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/net/bluetooth/qcom,wcn3950-bt.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm WCN3950/WCN3988 Bluetooth
maintainers:
- Balakrishna Godavarthi <quic_bgodavar@quicinc.com>
- Rocky Liao <quic_rjliao@quicinc.com>
properties:
compatible:
enum:
- qcom,wcn3950-bt
- qcom,wcn3988-bt
enable-gpios:
maxItems: 1
swctrl-gpios:
maxItems: 1
description: gpio specifier is used to find status
of clock supply to SoC
vddch0-supply:
description: VDD_CH0 supply regulator handle
vddio-supply:
description: VDD_IO supply regulator handle
vddrf-supply:
description: VDD_RF supply regulator handle
vddxo-supply:
description: VDD_XO supply regulator handle
required:
- compatible
- vddch0-supply
- vddio-supply
- vddrf-supply
- vddxo-supply
allOf:
- $ref: bluetooth-controller.yaml#
- $ref: qcom,bluetooth-common.yaml
- $ref: /schemas/serial/serial-peripheral-props.yaml#
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
serial {
bluetooth {
compatible = "qcom,wcn3950-bt";
enable-gpios = <&tlmm 87 GPIO_ACTIVE_HIGH>;
max-speed = <3200000>;
vddch0-supply = <&pm4125_l22>;
vddio-supply = <&pm4125_l15>;
vddrf-supply = <&pm4125_l10>;
vddxo-supply = <&pm4125_l13>;
};
};

View File

@ -0,0 +1,66 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/net/bluetooth/qcom,wcn3990-bt.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm WCN3990/WCN3991/WCN3998 Bluetooth
maintainers:
- Balakrishna Godavarthi <quic_bgodavar@quicinc.com>
- Rocky Liao <quic_rjliao@quicinc.com>
properties:
compatible:
enum:
- qcom,wcn3990-bt
- qcom,wcn3991-bt
- qcom,wcn3998-bt
clocks:
items:
- description: External low-power 32.768 kHz clock input
vddch0-supply:
description: VDD_CH0 supply regulator handle
vddch1-supply:
description: VDD_CH1 supply regulator handle
vddio-supply:
description: VDD_IO supply regulator handle
vddrf-supply:
description: VDD_RF supply regulator handle
vddxo-supply:
description: VDD_XO supply regulator handle
required:
- compatible
- vddch0-supply
- vddio-supply
- vddrf-supply
- vddxo-supply
allOf:
- $ref: bluetooth-controller.yaml#
- $ref: qcom,bluetooth-common.yaml
- $ref: /schemas/serial/serial-peripheral-props.yaml#
unevaluatedProperties: false
examples:
- |
serial {
bluetooth {
compatible = "qcom,wcn3990-bt";
firmware-name = "crnv21.bin";
max-speed = <3200000>;
vddio-supply = <&vreg_s4a_1p8>;
vddch0-supply = <&vreg_l25a_3p3>;
vddch1-supply = <&vreg_l23a_3p3>;
vddrf-supply = <&vreg_l17a_1p3>;
vddxo-supply = <&vreg_l7a_1p8>;
};
};

View File

@ -0,0 +1,91 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/net/bluetooth/qcom,wcn6750-bt.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm WCN6750 Bluetooth
maintainers:
- Balakrishna Godavarthi <quic_bgodavar@quicinc.com>
- Rocky Liao <quic_rjliao@quicinc.com>
properties:
compatible:
enum:
- qcom,wcn6750-bt
enable-gpios:
maxItems: 1
deprecated: true
swctrl-gpios:
maxItems: 1
description: gpio specifier is used to find status
of clock supply to SoC
deprecated: true
vddaon-supply:
description: VDD_AON supply regulator handle
vddasd-supply:
description: VDD_ASD supply regulator handle
deprecated: true
vddbtcmx-supply:
description: VDD_BT_CMX supply regulator handle
vddbtcxmx-supply:
description: VDD_BT_CXMX supply regulator handle
deprecated: true
vddio-supply:
description: VDD_IO supply regulator handle
deprecated: true
vddrfa0p8-supply:
description: VDD_RFA_0P8 supply regulator handle
vddrfa1p2-supply:
description: VDD_RFA_1P2 supply regulator handle
vddrfa1p7-supply:
description: VDD_RFA_1P7 supply regulator handle
vddrfa2p2-supply:
description: VDD_RFA_2P2 supply regulator handle
vddrfacmn-supply:
description: VDD_RFA_CMN supply regulator handle
required:
- compatible
- vddaon-supply
- vddrfa0p8-supply
- vddrfa1p2-supply
- vddrfa1p7-supply
- vddrfacmn-supply
allOf:
- $ref: bluetooth-controller.yaml#
- $ref: qcom,bluetooth-common.yaml
- $ref: /schemas/serial/serial-peripheral-props.yaml#
unevaluatedProperties: false
examples:
- |
serial {
bluetooth {
compatible = "qcom,wcn6750-bt";
firmware-name = "msnv11.bin";
max-speed = <3200000>;
vddaon-supply = <&vreg_pmu_aon_0p59>;
vddbtcmx-supply = <&vreg_pmu_btcmx_0p85>;
vddrfa0p8-supply = <&vreg_pmu_rfa_0p8>;
vddrfa1p2-supply = <&vreg_pmu_rfa_1p2>;
vddrfa1p7-supply = <&vreg_pmu_rfa_1p7>;
vddrfacmn-supply = <&vreg_pmu_rfa_cmn>;
};
};

View File

@ -0,0 +1,99 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/net/bluetooth/qcom,wcn6855-bt.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm WCN6855 Bluetooth
maintainers:
- Bartosz Golaszewski <brgl@bgdev.pl>
- Balakrishna Godavarthi <quic_bgodavar@quicinc.com>
- Rocky Liao <quic_rjliao@quicinc.com>
properties:
compatible:
enum:
- qcom,wcn6855-bt
enable-gpios:
maxItems: 1
deprecated: true
swctrl-gpios:
maxItems: 1
description: gpio specifier is used to find status
of clock supply to SoC
deprecated: true
vddaon-supply:
description: VDD_AON supply regulator handle
vddbtcmx-supply:
description: VDD_BT_CMX supply regulator handle
vddbtcxmx-supply:
description: VDD_BT_CXMX supply regulator handle
deprecated: true
vddio-supply:
description: VDD_IO supply regulator handle
deprecated: true
vddrfa0p8-supply:
description: VDD_RFA_0P8 supply regulator handle
vddrfa1p2-supply:
description: VDD_RFA_1P2 supply regulator handle
vddrfa1p7-supply:
description: VDD_RFA_1P7 supply regulator handle
deprecated: true
vddrfa1p8-supply:
description: VDD_RFA_1P8 supply regulator handle
vddrfacmn-supply:
description: VDD_RFA_CMN supply regulator handle
vddwlcx-supply:
description: VDD_WLCX supply regulator handle
vddwlmx-supply:
description: VDD_WLMX supply regulator handle
required:
- compatible
- vddaon-supply
- vddbtcmx-supply
- vddrfa0p8-supply
- vddrfa1p2-supply
- vddrfa1p8-supply
- vddrfacmn-supply
- vddwlcx-supply
- vddwlmx-supply
allOf:
- $ref: bluetooth-controller.yaml#
- $ref: qcom,bluetooth-common.yaml
- $ref: /schemas/serial/serial-peripheral-props.yaml#
unevaluatedProperties: false
examples:
- |
serial {
bluetooth {
compatible = "qcom,wcn6855-bt";
max-speed = <3000000>;
vddaon-supply = <&vreg_pmu_aon_0p8>;
vddbtcmx-supply = <&vreg_pmu_btcmx_0p8>;
vddrfa0p8-supply = <&vreg_pmu_rfa_0p8>;
vddrfa1p2-supply = <&vreg_pmu_rfa_1p2>;
vddrfa1p8-supply = <&vreg_pmu_rfa_1p7>;
vddrfacmn-supply = <&vreg_pmu_rfa_cmn_0p8>;
vddwlcx-supply = <&vreg_pmu_wlcx_0p8>;
vddwlmx-supply = <&vreg_pmu_wlmx_0p8>;
};
};

View File

@ -0,0 +1,94 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/net/bluetooth/qcom,wcn7850-bt.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm WCN7850 Bluetooth
maintainers:
- Bartosz Golaszewski <brgl@bgdev.pl>
- Balakrishna Godavarthi <quic_bgodavar@quicinc.com>
- Rocky Liao <quic_rjliao@quicinc.com>
properties:
compatible:
enum:
- qcom,wcn7850-bt
enable-gpios:
maxItems: 1
deprecated: true
swctrl-gpios:
maxItems: 1
description: gpio specifier is used to find status
of clock supply to SoC
deprecated: true
vddaon-supply:
description: VDD_AON supply regulator handle
vdddig-supply:
description: VDD_DIG supply regulator handle
deprecated: true
vddio-supply:
description: VDD_IO supply regulator handle
deprecated: true
vddrfa0p8-supply:
description: VDD_RFA_0P8 supply regulator handle
vddrfa1p2-supply:
description: VDD_RFA_1P2 supply regulator handle
vddrfa1p8-supply:
description: VDD_RFA_1P8 supply regulator handle
vddrfa1p9-supply:
description: VDD_RFA_1P9 supply regulator handle
deprecated: true
vddrfacmn-supply:
description: VDD_RFA_CMN supply regulator handle
vddwlcx-supply:
description: VDD_WLCX supply regulator handle
vddwlmx-supply:
description: VDD_WLMX supply regulator handle
required:
- compatible
- vddrfacmn-supply
- vddaon-supply
- vddwlcx-supply
- vddwlmx-supply
- vddrfa0p8-supply
- vddrfa1p2-supply
- vddrfa1p8-supply
allOf:
- $ref: bluetooth-controller.yaml#
- $ref: qcom,bluetooth-common.yaml
- $ref: /schemas/serial/serial-peripheral-props.yaml#
unevaluatedProperties: false
examples:
- |
serial {
bluetooth {
compatible = "qcom,wcn7850-bt";
max-speed = <3200000>;
vddaon-supply = <&vreg_pmu_aon_0p59>;
vddrfa0p8-supply = <&vreg_pmu_rfa_0p8>;
vddrfa1p2-supply = <&vreg_pmu_rfa_1p2>;
vddrfa1p8-supply = <&vreg_pmu_rfa_1p8>;
vddrfacmn-supply = <&vreg_pmu_rfa_cmn>;
vddwlcx-supply = <&vreg_pmu_wlcx_0p8>;
vddwlmx-supply = <&vreg_pmu_wlmx_0p85>;
};
};

View File

@ -1,259 +0,0 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/net/bluetooth/qualcomm-bluetooth.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Bluetooth Chips
maintainers:
- Balakrishna Godavarthi <quic_bgodavar@quicinc.com>
- Rocky Liao <quic_rjliao@quicinc.com>
description:
This binding describes Qualcomm UART-attached bluetooth chips.
properties:
compatible:
enum:
- qcom,qca2066-bt
- qcom,qca6174-bt
- qcom,qca9377-bt
- qcom,wcn3950-bt
- qcom,wcn3988-bt
- qcom,wcn3990-bt
- qcom,wcn3991-bt
- qcom,wcn3998-bt
- qcom,qca6390-bt
- qcom,wcn6750-bt
- qcom,wcn6855-bt
- qcom,wcn7850-bt
enable-gpios:
maxItems: 1
description: gpio specifier used to enable chip
swctrl-gpios:
maxItems: 1
description: gpio specifier is used to find status
of clock supply to SoC
clocks:
maxItems: 1
description: clock provided to the controller (SUSCLK_32KHZ)
vddio-supply:
description: VDD_IO supply regulator handle
vddxo-supply:
description: VDD_XO supply regulator handle
vddrf-supply:
description: VDD_RF supply regulator handle
vddch0-supply:
description: VDD_CH0 supply regulator handle
vddch1-supply:
description: VDD_CH1 supply regulator handle
vddaon-supply:
description: VDD_AON supply regulator handle
vdddig-supply:
description: VDD_DIG supply regulator handle
vddbtcmx-supply:
description: VDD_BT_CMX supply regulator handle
vddbtcxmx-supply:
description: VDD_BT_CXMX supply regulator handle
vddrfacmn-supply:
description: VDD_RFA_CMN supply regulator handle
vddrfa0p8-supply:
description: VDD_RFA_0P8 supply regulator handle
vddrfa1p7-supply:
description: VDD_RFA_1P7 supply regulator handle
vddrfa1p8-supply:
description: VDD_RFA_1P8 supply regulator handle
vddrfa1p2-supply:
description: VDD_RFA_1P2 supply regulator handle
vddrfa1p9-supply:
description: VDD_RFA_1P9 supply regulator handle
vddrfa2p2-supply:
description: VDD_RFA_2P2 supply regulator handle
vddasd-supply:
description: VDD_ASD supply regulator handle
vddwlcx-supply:
description: VDD_WLCX supply regulator handle
vddwlmx-supply:
description: VDD_WLMX supply regulator handle
max-speed: true
firmware-name:
minItems: 1
items:
- description: specify the name of nvm firmware to load
- description: specify the name of rampatch firmware to load
local-bd-address: true
qcom,local-bd-address-broken:
type: boolean
description:
boot firmware is incorrectly passing the address in big-endian order
required:
- compatible
additionalProperties: false
allOf:
- $ref: bluetooth-controller.yaml#
- $ref: /schemas/serial/serial-peripheral-props.yaml#
- if:
properties:
compatible:
contains:
enum:
- qcom,qca2066-bt
- qcom,qca6174-bt
then:
required:
- enable-gpios
- clocks
- if:
properties:
compatible:
contains:
enum:
- qcom,wcn3950-bt
- qcom,wcn3988-bt
- qcom,wcn3990-bt
- qcom,wcn3991-bt
- qcom,wcn3998-bt
then:
required:
- vddio-supply
- vddxo-supply
- vddrf-supply
- vddch0-supply
- if:
properties:
compatible:
contains:
enum:
- qcom,wcn6750-bt
then:
required:
- vddaon-supply
- vddrfacmn-supply
- vddrfa0p8-supply
- vddrfa1p7-supply
- vddrfa1p2-supply
- if:
properties:
compatible:
contains:
enum:
- qcom,wcn6855-bt
then:
required:
- vddrfacmn-supply
- vddaon-supply
- vddwlcx-supply
- vddwlmx-supply
- vddbtcmx-supply
- vddrfa0p8-supply
- vddrfa1p2-supply
- vddrfa1p8-supply
- if:
properties:
compatible:
contains:
enum:
- qcom,wcn7850-bt
then:
required:
- vddrfacmn-supply
- vddaon-supply
- vddwlcx-supply
- vddwlmx-supply
- vddrfa0p8-supply
- vddrfa1p2-supply
- vddrfa1p8-supply
- if:
properties:
compatible:
contains:
enum:
- qcom,qca6390-bt
then:
required:
- vddrfacmn-supply
- vddaon-supply
- vddbtcmx-supply
- vddrfa0p8-supply
- vddrfa1p2-supply
- vddrfa1p7-supply
examples:
- |
#include <dt-bindings/gpio/gpio.h>
serial {
bluetooth {
compatible = "qcom,qca6174-bt";
enable-gpios = <&pm8994_gpios 19 GPIO_ACTIVE_HIGH>;
clocks = <&divclk4>;
firmware-name = "nvm_00440302.bin";
};
};
- |
serial {
bluetooth {
compatible = "qcom,wcn3990-bt";
vddio-supply = <&vreg_s4a_1p8>;
vddxo-supply = <&vreg_l7a_1p8>;
vddrf-supply = <&vreg_l17a_1p3>;
vddch0-supply = <&vreg_l25a_3p3>;
max-speed = <3200000>;
firmware-name = "crnv21.bin";
};
};
- |
serial {
bluetooth {
compatible = "qcom,wcn6750-bt";
pinctrl-names = "default";
pinctrl-0 = <&bt_en_default>;
enable-gpios = <&tlmm 85 GPIO_ACTIVE_HIGH>;
swctrl-gpios = <&tlmm 86 GPIO_ACTIVE_HIGH>;
vddio-supply = <&vreg_l19b_1p8>;
vddaon-supply = <&vreg_s7b_0p9>;
vddbtcxmx-supply = <&vreg_s7b_0p9>;
vddrfacmn-supply = <&vreg_s7b_0p9>;
vddrfa0p8-supply = <&vreg_s7b_0p9>;
vddrfa1p7-supply = <&vreg_s1b_1p8>;
vddrfa1p2-supply = <&vreg_s8b_1p2>;
vddrfa2p2-supply = <&vreg_s1c_2p2>;
vddasd-supply = <&vreg_l11c_2p8>;
max-speed = <3200000>;
firmware-name = "msnv11.bin";
};
};

View File

@ -21379,6 +21379,7 @@ QUALCOMM BLUETOOTH DRIVER
M: Bartosz Golaszewski <brgl@kernel.org>
L: linux-arm-msm@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/net/bluetooth/qcom,*
F: drivers/bluetooth/btqca.[ch]
F: drivers/bluetooth/btqcomsmd.c
F: drivers/bluetooth/hci_qca.c

View File

@ -1190,8 +1190,7 @@ static int btintel_pcie_recv_frame(struct btintel_pcie_data *data,
skb = NULL; /* skb is freed in the callee */
exit_error:
if (skb)
kfree_skb(skb);
kfree_skb(skb);
if (ret)
hdev->stat.err_rx++;

View File

@ -1472,7 +1472,6 @@ static void btmtksdio_remove(struct sdio_func *func)
hci_free_dev(hdev);
}
#ifdef CONFIG_PM
static int btmtksdio_runtime_suspend(struct device *dev)
{
struct sdio_func *func = dev_to_sdio_func(dev);
@ -1542,18 +1541,13 @@ static const struct dev_pm_ops btmtksdio_pm_ops = {
RUNTIME_PM_OPS(btmtksdio_runtime_suspend, btmtksdio_runtime_resume, NULL)
};
#define BTMTKSDIO_PM_OPS (&btmtksdio_pm_ops)
#else /* CONFIG_PM */
#define BTMTKSDIO_PM_OPS NULL
#endif /* CONFIG_PM */
static struct sdio_driver btmtksdio_driver = {
.name = "btmtksdio",
.probe = btmtksdio_probe,
.remove = btmtksdio_remove,
.id_table = btmtksdio_table,
.drv = {
.pm = BTMTKSDIO_PM_OPS,
.pm = pm_ptr(&btmtksdio_pm_ops),
}
};

View File

@ -1947,8 +1947,7 @@ static void nxp_serdev_remove(struct serdev_device *serdev)
hci_free_dev(hdev);
}
#ifdef CONFIG_PM_SLEEP
static int nxp_serdev_suspend(struct device *dev)
static int __maybe_unused nxp_serdev_suspend(struct device *dev)
{
struct btnxpuart_dev *nxpdev = dev_get_drvdata(dev);
struct ps_data *psdata = &nxpdev->psdata;
@ -1962,7 +1961,7 @@ static int nxp_serdev_suspend(struct device *dev)
return 0;
}
static int nxp_serdev_resume(struct device *dev)
static int __maybe_unused nxp_serdev_resume(struct device *dev)
{
struct btnxpuart_dev *nxpdev = dev_get_drvdata(dev);
struct ps_data *psdata = &nxpdev->psdata;
@ -1975,7 +1974,6 @@ static int nxp_serdev_resume(struct device *dev)
ps_control(psdata->hdev, PS_STATE_AWAKE);
return 0;
}
#endif
#ifdef CONFIG_DEV_COREDUMP
static void nxp_serdev_coredump(struct device *dev)

View File

@ -581,28 +581,11 @@ static int qca_download_firmware(struct hci_dev *hdev,
ret = request_firmware(&fw, config->fwname, &hdev->dev);
if (ret) {
/* For WCN6750, if mbn file is not present then check for
* tlv file.
*/
if (soc_type == QCA_WCN6750 && config->type == ELF_TYPE_PATCH) {
bt_dev_dbg(hdev, "QCA Failed to request file: %s (%d)",
config->fwname, ret);
config->type = TLV_TYPE_PATCH;
snprintf(config->fwname, sizeof(config->fwname),
"qca/msbtfw%02x.tlv", rom_ver);
bt_dev_info(hdev, "QCA Downloading %s", config->fwname);
ret = request_firmware(&fw, config->fwname, &hdev->dev);
if (ret) {
bt_dev_err(hdev, "QCA Failed to request file: %s (%d)",
config->fwname, ret);
return ret;
}
}
/* If the board-specific file is missing, try loading the default
* one, unless that was attempted already.
*/
else if (config->type == TLV_TYPE_NVM &&
qca_get_alt_nvm_file(config->fwname, sizeof(config->fwname))) {
if (config->type == TLV_TYPE_NVM &&
qca_get_alt_nvm_file(config->fwname, sizeof(config->fwname))) {
bt_dev_info(hdev, "QCA Downloading %s", config->fwname);
ret = request_firmware(&fw, config->fwname, &hdev->dev);
if (ret) {
@ -847,8 +830,12 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
"qca/msbtfw%02x.mbn", rom_ver);
break;
case QCA_WCN6855:
/* Due to historical reasons, WCN685x chip has been using firmware
* without the "wcn" prefix. The mapping between the chip and its
* corresponding firmware has now been corrected.
*/
snprintf(config.fwname, sizeof(config.fwname),
"qca/hpbtfw%02x.tlv", rom_ver);
"qca/wcnhpbtfw%02x.tlv", rom_ver);
break;
case QCA_WCN7850:
snprintf(config.fwname, sizeof(config.fwname),
@ -861,8 +848,26 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
}
err = qca_download_firmware(hdev, &config, soc_type, rom_ver);
/* For WCN6750, if mbn file is not present then check for
* tlv file.
*/
if (err < 0 && soc_type == QCA_WCN6750) {
bt_dev_dbg(hdev, "QCA Failed to request file: %s (%d)",
config.fwname, err);
config.type = TLV_TYPE_PATCH;
snprintf(config.fwname, sizeof(config.fwname),
"qca/msbtfw%02x.tlv", rom_ver);
bt_dev_info(hdev, "QCA Downloading %s", config.fwname);
err = qca_download_firmware(hdev, &config, soc_type, rom_ver);
} else if (err < 0 && !rampatch_name && soc_type == QCA_WCN6855) {
snprintf(config.fwname, sizeof(config.fwname),
"qca/hpbtfw%02x.tlv", rom_ver);
err = qca_download_firmware(hdev, &config, soc_type, rom_ver);
}
if (err < 0) {
bt_dev_err(hdev, "QCA Failed to download patch (%d)", err);
bt_dev_err(hdev, "QCA Failed to request file: %s (%d)",
config.fwname, err);
return err;
}
@ -923,7 +928,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
case QCA_WCN6855:
qca_read_fw_board_id(hdev, &boardid);
qca_get_nvm_name_by_board(config.fwname, sizeof(config.fwname),
"hpnv", soc_type, ver, rom_ver, boardid);
"wcnhpnv", soc_type, ver, rom_ver, boardid);
break;
case QCA_WCN7850:
qca_get_nvm_name_by_board(config.fwname, sizeof(config.fwname),
@ -936,8 +941,15 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
}
err = qca_download_firmware(hdev, &config, soc_type, rom_ver);
if (err < 0 && !firmware_name && soc_type == QCA_WCN6855) {
qca_get_nvm_name_by_board(config.fwname, sizeof(config.fwname),
"hpnv", soc_type, ver, rom_ver, boardid);
err = qca_download_firmware(hdev, &config, soc_type, rom_ver);
}
if (err < 0) {
bt_dev_err(hdev, "QCA Failed to download NVM (%d)", err);
bt_dev_err(hdev, "QCA Failed to request file: %s (%d)",
config.fwname, err);
return err;
}

View File

@ -521,12 +521,16 @@ static const struct usb_device_id quirks_table[] = {
{ USB_DEVICE(0x0bda, 0xb850), .driver_info = BTUSB_REALTEK },
{ USB_DEVICE(0x13d3, 0x3600), .driver_info = BTUSB_REALTEK },
{ USB_DEVICE(0x13d3, 0x3601), .driver_info = BTUSB_REALTEK },
{ USB_DEVICE(0x0489, 0xe112), .driver_info = BTUSB_REALTEK |
BTUSB_WIDEBAND_SPEECH },
/* Realtek 8851BU Bluetooth devices */
{ USB_DEVICE(0x3625, 0x010b), .driver_info = BTUSB_REALTEK |
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x2001, 0x332a), .driver_info = BTUSB_REALTEK |
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x7392, 0xe611), .driver_info = BTUSB_REALTEK |
BTUSB_WIDEBAND_SPEECH },
/* Realtek 8852AE Bluetooth devices */
{ USB_DEVICE(0x0bda, 0x2852), .driver_info = BTUSB_REALTEK |
@ -557,6 +561,8 @@ static const struct usb_device_id quirks_table[] = {
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x13d3, 0x3592), .driver_info = BTUSB_REALTEK |
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x13d3, 0x3612), .driver_info = BTUSB_REALTEK |
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x0489, 0xe122), .driver_info = BTUSB_REALTEK |
BTUSB_WIDEBAND_SPEECH },
@ -577,8 +583,6 @@ static const struct usb_device_id quirks_table[] = {
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x13d3, 0x3591), .driver_info = BTUSB_REALTEK |
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x13d3, 0x3618), .driver_info = BTUSB_REALTEK |
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x0489, 0xe123), .driver_info = BTUSB_REALTEK |
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x0489, 0xe125), .driver_info = BTUSB_REALTEK |
@ -637,6 +641,8 @@ static const struct usb_device_id quirks_table[] = {
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x13d3, 0x3622), .driver_info = BTUSB_MEDIATEK |
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x0489, 0xe158), .driver_info = BTUSB_MEDIATEK |
BTUSB_WIDEBAND_SPEECH },
/* Additional MediaTek MT7921 Bluetooth devices */
{ USB_DEVICE(0x0489, 0xe0c8), .driver_info = BTUSB_MEDIATEK |
@ -773,6 +779,7 @@ static const struct usb_device_id quirks_table[] = {
/* Additional Realtek 8723BU Bluetooth devices */
{ USB_DEVICE(0x7392, 0xa611), .driver_info = BTUSB_REALTEK },
{ USB_DEVICE(0x2c0a, 0x8761), .driver_info = BTUSB_REALTEK },
/* Additional Realtek 8723DE Bluetooth devices */
{ USB_DEVICE(0x0bda, 0xb009), .driver_info = BTUSB_REALTEK },
@ -4462,17 +4469,17 @@ static void btusb_disconnect(struct usb_interface *intf)
kfree(data);
}
#ifdef CONFIG_PM
static int btusb_suspend(struct usb_interface *intf, pm_message_t message)
{
struct btusb_data *data = usb_get_intfdata(intf);
BT_DBG("intf %p", intf);
/* Don't auto-suspend if there are connections; external suspend calls
* shall never fail.
/* Don't auto-suspend if there are connections or discovery in
* progress; external suspend calls shall never fail.
*/
if (PMSG_IS_AUTO(message) && hci_conn_count(data->hdev))
if (PMSG_IS_AUTO(message) &&
(hci_conn_count(data->hdev) || hci_discovery_active(data->hdev)))
return -EBUSY;
if (data->suspend_count++)
@ -4616,7 +4623,6 @@ static int btusb_resume(struct usb_interface *intf)
return err;
}
#endif
#ifdef CONFIG_DEV_COREDUMP
static void btusb_coredump(struct device *dev)
@ -4633,10 +4639,8 @@ static struct usb_driver btusb_driver = {
.name = "btusb",
.probe = btusb_probe,
.disconnect = btusb_disconnect,
#ifdef CONFIG_PM
.suspend = btusb_suspend,
.resume = btusb_resume,
#endif
.suspend = pm_ptr(btusb_suspend),
.resume = pm_ptr(btusb_resume),
.id_table = btusb_table,
.supports_autosuspend = 1,
.disable_hub_initiated_lpm = 1,

View File

@ -2416,8 +2416,9 @@ static int bcm4377_probe(struct pci_dev *pdev, const struct pci_device_id *id)
hdev);
}
static int bcm4377_suspend(struct pci_dev *pdev, pm_message_t state)
static int bcm4377_suspend(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
struct bcm4377_data *bcm4377 = pci_get_drvdata(pdev);
int ret;
@ -2431,8 +2432,9 @@ static int bcm4377_suspend(struct pci_dev *pdev, pm_message_t state)
return 0;
}
static int bcm4377_resume(struct pci_dev *pdev)
static int bcm4377_resume(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
struct bcm4377_data *bcm4377 = pci_get_drvdata(pdev);
iowrite32(BCM4377_BAR0_SLEEP_CONTROL_UNQUIESCE,
@ -2441,6 +2443,8 @@ static int bcm4377_resume(struct pci_dev *pdev)
return hci_resume_dev(bcm4377->hdev);
}
static DEFINE_SIMPLE_DEV_PM_OPS(bcm4377_ops, bcm4377_suspend, bcm4377_resume);
static const struct dmi_system_id bcm4377_dmi_board_table[] = {
{
.matches = {
@ -2541,8 +2545,7 @@ static struct pci_driver bcm4377_pci_driver = {
.name = "hci_bcm4377",
.id_table = bcm4377_devid_table,
.probe = bcm4377_probe,
.suspend = bcm4377_suspend,
.resume = bcm4377_resume,
.driver.pm = &bcm4377_ops,
};
module_pci_driver(bcm4377_pci_driver);

View File

@ -126,7 +126,6 @@ static int intel_wait_booting(struct hci_uart *hu)
return err;
}
#ifdef CONFIG_PM
static int intel_wait_lpm_transaction(struct hci_uart *hu)
{
struct intel_data *intel = hu->priv;
@ -237,7 +236,6 @@ static int intel_lpm_resume(struct hci_uart *hu)
return 0;
}
#endif /* CONFIG_PM */
static int intel_lpm_host_wake(struct hci_uart *hu)
{
@ -1066,7 +1064,6 @@ static const struct acpi_device_id intel_acpi_match[] = {
MODULE_DEVICE_TABLE(acpi, intel_acpi_match);
#endif
#ifdef CONFIG_PM
static int intel_suspend_device(struct device *dev)
{
struct intel_device *idev = dev_get_drvdata(dev);
@ -1090,10 +1087,8 @@ static int intel_resume_device(struct device *dev)
return 0;
}
#endif
#ifdef CONFIG_PM_SLEEP
static int intel_suspend(struct device *dev)
static int __maybe_unused intel_suspend(struct device *dev)
{
struct intel_device *idev = dev_get_drvdata(dev);
@ -1103,7 +1098,7 @@ static int intel_suspend(struct device *dev)
return intel_suspend_device(dev);
}
static int intel_resume(struct device *dev)
static int __maybe_unused intel_resume(struct device *dev)
{
struct intel_device *idev = dev_get_drvdata(dev);
@ -1112,7 +1107,6 @@ static int intel_resume(struct device *dev)
return intel_resume_device(dev);
}
#endif
static const struct dev_pm_ops intel_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(intel_suspend, intel_resume)

View File

@ -685,6 +685,8 @@ static int hci_uart_register_dev(struct hci_uart *hu)
return err;
}
set_bit(HCI_UART_PROTO_INIT, &hu->flags);
if (test_bit(HCI_UART_INIT_PENDING, &hu->hdev_flags))
return 0;
@ -712,8 +714,6 @@ static int hci_uart_set_proto(struct hci_uart *hu, int id)
hu->proto = p;
set_bit(HCI_UART_PROTO_INIT, &hu->flags);
err = hci_uart_register_dev(hu);
if (err) {
return err;

View File

@ -87,6 +87,7 @@ enum qca_flags {
enum qca_capabilities {
QCA_CAP_WIDEBAND_SPEECH = BIT(0),
QCA_CAP_VALID_LE_STATES = BIT(1),
QCA_CAP_HFP_HW_OFFLOAD = BIT(2),
};
/* HCI_IBS transmit side sleep protocol states */
@ -229,6 +230,7 @@ struct qca_serdev {
u32 init_speed;
u32 oper_speed;
bool bdaddr_property_broken;
bool support_hfp_hw_offload;
const char *firmware_name[2];
};
@ -1653,6 +1655,39 @@ static void qca_hw_error(struct hci_dev *hdev, u8 code)
skb_queue_purge(&qca->rx_memdump_q);
}
/*
* If the BT chip's bt_en pin is connected to a 3.3V power supply via
* hardware and always stays high, driver cannot control the bt_en pin.
* As a result, during SSR (SubSystem Restart), QCA_SSR_TRIGGERED and
* QCA_IBS_DISABLED flags cannot be cleared, which leads to a reset
* command timeout.
* Add an msleep delay to ensure controller completes the SSR process.
*
* Host will not download the firmware after SSR, controller to remain
* in the IBS_WAKE state, and the host needs to synchronize with it
*
* Since the bluetooth chip has been reset, clear the memdump state.
*/
if (!hci_test_quirk(hu->hdev, HCI_QUIRK_NON_PERSISTENT_SETUP)) {
/*
* When the SSR (SubSystem Restart) duration exceeds 2 seconds,
* it triggers host tx_idle_delay, which sets host TX state
* to sleep. Reset tx_idle_timer after SSR to prevent
* host enter TX IBS_Sleep mode.
*/
mod_timer(&qca->tx_idle_timer, jiffies +
msecs_to_jiffies(qca->tx_idle_delay));
/* Controller reset completion time is 50ms */
msleep(50);
clear_bit(QCA_SSR_TRIGGERED, &qca->flags);
clear_bit(QCA_IBS_DISABLED, &qca->flags);
qca->tx_ibs_state = HCI_IBS_TX_AWAKE;
qca->memdump_state = QCA_MEMDUMP_IDLE;
}
clear_bit(QCA_HW_ERROR_EVENT, &qca->flags);
}
@ -1879,7 +1914,7 @@ static int qca_setup(struct hci_uart *hu)
const char *rampatch_name = qca_get_rampatch_name(hu);
int ret;
struct qca_btsoc_version ver;
struct qca_serdev *qcadev;
struct qca_serdev *qcadev = serdev_device_get_drvdata(hu->serdev);
const char *soc_name;
ret = qca_check_speeds(hu);
@ -1943,7 +1978,6 @@ static int qca_setup(struct hci_uart *hu)
case QCA_WCN6750:
case QCA_WCN6855:
case QCA_WCN7850:
qcadev = serdev_device_get_drvdata(hu->serdev);
if (qcadev->bdaddr_property_broken)
hci_set_quirk(hdev, HCI_QUIRK_BDADDR_PROPERTY_BROKEN);
@ -2033,7 +2067,7 @@ static int qca_setup(struct hci_uart *hu)
else
hu->hdev->set_bdaddr = qca_set_bdaddr;
if (soc_type == QCA_QCA2066)
if (qcadev->support_hfp_hw_offload)
qca_configure_hfp_offload(hdev);
qca->fw_version = le16_to_cpu(ver.patch_ver);
@ -2117,7 +2151,8 @@ static const struct qca_device_data qca_soc_data_wcn3998 __maybe_unused = {
static const struct qca_device_data qca_soc_data_qca2066 __maybe_unused = {
.soc_type = QCA_QCA2066,
.num_vregs = 0,
.capabilities = QCA_CAP_WIDEBAND_SPEECH | QCA_CAP_VALID_LE_STATES,
.capabilities = QCA_CAP_WIDEBAND_SPEECH | QCA_CAP_VALID_LE_STATES |
QCA_CAP_HFP_HW_OFFLOAD,
};
static const struct qca_device_data qca_soc_data_qca6390 __maybe_unused = {
@ -2153,7 +2188,8 @@ static const struct qca_device_data qca_soc_data_wcn6855 __maybe_unused = {
{ "vddrfa1p2", 257000 },
},
.num_vregs = 6,
.capabilities = QCA_CAP_WIDEBAND_SPEECH | QCA_CAP_VALID_LE_STATES,
.capabilities = QCA_CAP_WIDEBAND_SPEECH | QCA_CAP_VALID_LE_STATES |
QCA_CAP_HFP_HW_OFFLOAD,
};
static const struct qca_device_data qca_soc_data_wcn7850 __maybe_unused = {
@ -2167,7 +2203,8 @@ static const struct qca_device_data qca_soc_data_wcn7850 __maybe_unused = {
{ "vddrfa1p9", 302000 },
},
.num_vregs = 6,
.capabilities = QCA_CAP_WIDEBAND_SPEECH | QCA_CAP_VALID_LE_STATES,
.capabilities = QCA_CAP_WIDEBAND_SPEECH | QCA_CAP_VALID_LE_STATES |
QCA_CAP_HFP_HW_OFFLOAD,
};
static void qca_power_shutdown(struct hci_uart *hu)
@ -2502,6 +2539,9 @@ static int qca_serdev_probe(struct serdev_device *serdev)
if (!(data->capabilities & QCA_CAP_VALID_LE_STATES))
hci_set_quirk(hdev, HCI_QUIRK_BROKEN_LE_STATES);
if (data->capabilities & QCA_CAP_HFP_HW_OFFLOAD)
qcadev->support_hfp_hw_offload = true;
}
return 0;

View File

@ -130,21 +130,30 @@ struct bt_voice {
#define BT_RCVMTU 13
#define BT_PHY 14
#define BT_PHY_BR_1M_1SLOT 0x00000001
#define BT_PHY_BR_1M_3SLOT 0x00000002
#define BT_PHY_BR_1M_5SLOT 0x00000004
#define BT_PHY_EDR_2M_1SLOT 0x00000008
#define BT_PHY_EDR_2M_3SLOT 0x00000010
#define BT_PHY_EDR_2M_5SLOT 0x00000020
#define BT_PHY_EDR_3M_1SLOT 0x00000040
#define BT_PHY_EDR_3M_3SLOT 0x00000080
#define BT_PHY_EDR_3M_5SLOT 0x00000100
#define BT_PHY_LE_1M_TX 0x00000200
#define BT_PHY_LE_1M_RX 0x00000400
#define BT_PHY_LE_2M_TX 0x00000800
#define BT_PHY_LE_2M_RX 0x00001000
#define BT_PHY_LE_CODED_TX 0x00002000
#define BT_PHY_LE_CODED_RX 0x00004000
#define BT_PHY_BR_1M_1SLOT BIT(0)
#define BT_PHY_BR_1M_3SLOT BIT(1)
#define BT_PHY_BR_1M_5SLOT BIT(2)
#define BT_PHY_EDR_2M_1SLOT BIT(3)
#define BT_PHY_EDR_2M_3SLOT BIT(4)
#define BT_PHY_EDR_2M_5SLOT BIT(5)
#define BT_PHY_EDR_3M_1SLOT BIT(6)
#define BT_PHY_EDR_3M_3SLOT BIT(7)
#define BT_PHY_EDR_3M_5SLOT BIT(8)
#define BT_PHY_LE_1M_TX BIT(9)
#define BT_PHY_LE_1M_RX BIT(10)
#define BT_PHY_LE_2M_TX BIT(11)
#define BT_PHY_LE_2M_RX BIT(12)
#define BT_PHY_LE_CODED_TX BIT(13)
#define BT_PHY_LE_CODED_RX BIT(14)
#define BT_PHY_BREDR_MASK (BT_PHY_BR_1M_1SLOT | BT_PHY_BR_1M_3SLOT | \
BT_PHY_BR_1M_5SLOT | BT_PHY_EDR_2M_1SLOT | \
BT_PHY_EDR_2M_3SLOT | BT_PHY_EDR_2M_5SLOT | \
BT_PHY_EDR_3M_1SLOT | BT_PHY_EDR_3M_3SLOT | \
BT_PHY_EDR_3M_5SLOT)
#define BT_PHY_LE_MASK (BT_PHY_LE_1M_TX | BT_PHY_LE_1M_RX | \
BT_PHY_LE_2M_TX | BT_PHY_LE_2M_RX | \
BT_PHY_LE_CODED_TX | BT_PHY_LE_CODED_RX)
#define BT_MODE 15
@ -173,7 +182,7 @@ struct bt_iso_io_qos {
__u32 interval;
__u16 latency;
__u16 sdu;
__u8 phy;
__u8 phys;
__u8 rtn;
};
@ -212,9 +221,9 @@ struct bt_iso_qos {
};
};
#define BT_ISO_PHY_1M 0x01
#define BT_ISO_PHY_2M 0x02
#define BT_ISO_PHY_CODED 0x04
#define BT_ISO_PHY_1M BIT(0)
#define BT_ISO_PHY_2M BIT(1)
#define BT_ISO_PHY_CODED BIT(2)
#define BT_ISO_PHY_ANY (BT_ISO_PHY_1M | BT_ISO_PHY_2M | \
BT_ISO_PHY_CODED)

View File

@ -654,6 +654,8 @@ enum {
#define HCI_LE_ISO_BROADCASTER 0x40
#define HCI_LE_ISO_SYNC_RECEIVER 0x80
#define HCI_LE_LL_EXT_FEATURE 0x80
#define HCI_LE_CS 0x40
#define HCI_LE_CS_HOST 0x80
/* Connection modes */
#define HCI_CM_ACTIVE 0x0000
@ -1883,6 +1885,15 @@ struct hci_cp_le_set_default_phy {
#define HCI_LE_SET_PHY_2M 0x02
#define HCI_LE_SET_PHY_CODED 0x04
#define HCI_OP_LE_SET_PHY 0x2032
struct hci_cp_le_set_phy {
__le16 handle;
__u8 all_phys;
__u8 tx_phys;
__u8 rx_phys;
__le16 phy_opts;
} __packed;
#define HCI_OP_LE_SET_EXT_SCAN_PARAMS 0x2041
struct hci_cp_le_set_ext_scan_params {
__u8 own_addr_type;
@ -2136,8 +2147,8 @@ struct hci_cis_params {
__u8 cis_id;
__le16 c_sdu;
__le16 p_sdu;
__u8 c_phy;
__u8 p_phy;
__u8 c_phys;
__u8 p_phys;
__u8 c_rtn;
__u8 p_rtn;
} __packed;
@ -2269,6 +2280,204 @@ struct hci_cp_le_read_all_remote_features {
__u8 pages;
} __packed;
/* Channel Sounding Commands */
#define HCI_OP_LE_CS_RD_LOCAL_SUPP_CAP 0x2089
struct hci_rp_le_cs_rd_local_supp_cap {
__u8 status;
__u8 num_config_supported;
__le16 max_consecutive_procedures_supported;
__u8 num_antennas_supported;
__u8 max_antenna_paths_supported;
__u8 roles_supported;
__u8 modes_supported;
__u8 rtt_capability;
__u8 rtt_aa_only_n;
__u8 rtt_sounding_n;
__u8 rtt_random_payload_n;
__le16 nadm_sounding_capability;
__le16 nadm_random_capability;
__u8 cs_sync_phys_supported;
__le16 subfeatures_supported;
__le16 t_ip1_times_supported;
__le16 t_ip2_times_supported;
__le16 t_fcs_times_supported;
__le16 t_pm_times_supported;
__u8 t_sw_time_supported;
__u8 tx_snr_capability;
} __packed;
#define HCI_OP_LE_CS_RD_RMT_SUPP_CAP 0x208A
struct hci_cp_le_cs_rd_local_supp_cap {
__le16 handle;
} __packed;
#define HCI_OP_LE_CS_WR_CACHED_RMT_SUPP_CAP 0x208B
struct hci_cp_le_cs_wr_cached_rmt_supp_cap {
__le16 handle;
__u8 num_config_supported;
__le16 max_consecutive_procedures_supported;
__u8 num_antennas_supported;
__u8 max_antenna_paths_supported;
__u8 roles_supported;
__u8 modes_supported;
__u8 rtt_capability;
__u8 rtt_aa_only_n;
__u8 rtt_sounding_n;
__u8 rtt_random_payload_n;
__le16 nadm_sounding_capability;
__le16 nadm_random_capability;
__u8 cs_sync_phys_supported;
__le16 subfeatures_supported;
__le16 t_ip1_times_supported;
__le16 t_ip2_times_supported;
__le16 t_fcs_times_supported;
__le16 t_pm_times_supported;
__u8 t_sw_time_supported;
__u8 tx_snr_capability;
} __packed;
struct hci_rp_le_cs_wr_cached_rmt_supp_cap {
__u8 status;
__le16 handle;
} __packed;
#define HCI_OP_LE_CS_SEC_ENABLE 0x208C
struct hci_cp_le_cs_sec_enable {
__le16 handle;
} __packed;
#define HCI_OP_LE_CS_SET_DEFAULT_SETTINGS 0x208D
struct hci_cp_le_cs_set_default_settings {
__le16 handle;
__u8 role_enable;
__u8 cs_sync_ant_sel;
__s8 max_tx_power;
} __packed;
struct hci_rp_le_cs_set_default_settings {
__u8 status;
__le16 handle;
} __packed;
#define HCI_OP_LE_CS_RD_RMT_FAE_TABLE 0x208E
struct hci_cp_le_cs_rd_rmt_fae_table {
__le16 handle;
} __packed;
#define HCI_OP_LE_CS_WR_CACHED_RMT_FAE_TABLE 0x208F
struct hci_cp_le_cs_wr_rmt_cached_fae_table {
__le16 handle;
__u8 remote_fae_table[72];
} __packed;
struct hci_rp_le_cs_wr_rmt_cached_fae_table {
__u8 status;
__le16 handle;
} __packed;
#define HCI_OP_LE_CS_CREATE_CONFIG 0x2090
struct hci_cp_le_cs_create_config {
__le16 handle;
__u8 config_id;
__u8 create_context;
__u8 main_mode_type;
__u8 sub_mode_type;
__u8 min_main_mode_steps;
__u8 max_main_mode_steps;
__u8 main_mode_repetition;
__u8 mode_0_steps;
__u8 role;
__u8 rtt_type;
__u8 cs_sync_phy;
__u8 channel_map[10];
__u8 channel_map_repetition;
__u8 channel_selection_type;
__u8 ch3c_shape;
__u8 ch3c_jump;
__u8 reserved;
} __packed;
#define HCI_OP_LE_CS_REMOVE_CONFIG 0x2091
struct hci_cp_le_cs_remove_config {
__le16 handle;
__u8 config_id;
} __packed;
#define HCI_OP_LE_CS_SET_CH_CLASSIFICATION 0x2092
struct hci_cp_le_cs_set_ch_classification {
__u8 ch_classification[10];
} __packed;
struct hci_rp_le_cs_set_ch_classification {
__u8 status;
} __packed;
#define HCI_OP_LE_CS_SET_PROC_PARAM 0x2093
struct hci_cp_le_cs_set_proc_param {
__le16 handle;
__u8 config_id;
__le16 max_procedure_len;
__le16 min_procedure_interval;
__le16 max_procedure_interval;
__le16 max_procedure_count;
__u8 min_subevent_len[3];
__u8 max_subevent_len[3];
__u8 tone_antenna_config_selection;
__u8 phy;
__u8 tx_power_delta;
__u8 preferred_peer_antenna;
__u8 snr_control_initiator;
__u8 snr_control_reflector;
} __packed;
struct hci_rp_le_cs_set_proc_param {
__u8 status;
__le16 handle;
} __packed;
#define HCI_OP_LE_CS_SET_PROC_ENABLE 0x2094
struct hci_cp_le_cs_set_proc_enable {
__le16 handle;
__u8 config_id;
__u8 enable;
} __packed;
#define HCI_OP_LE_CS_TEST 0x2095
struct hci_cp_le_cs_test {
__u8 main_mode_type;
__u8 sub_mode_type;
__u8 main_mode_repetition;
__u8 mode_0_steps;
__u8 role;
__u8 rtt_type;
__u8 cs_sync_phy;
__u8 cs_sync_antenna_selection;
__u8 subevent_len[3];
__le16 subevent_interval;
__u8 max_num_subevents;
__u8 transmit_power_level;
__u8 t_ip1_time;
__u8 t_ip2_time;
__u8 t_fcs_time;
__u8 t_pm_time;
__u8 t_sw_time;
__u8 tone_antenna_config_selection;
__u8 reserved;
__u8 snr_control_initiator;
__u8 snr_control_reflector;
__le16 drbg_nonce;
__u8 channel_map_repetition;
__le16 override_config;
__u8 override_parameters_length;
__u8 override_parameters_data[];
} __packed;
struct hci_rp_le_cs_test {
__u8 status;
} __packed;
#define HCI_OP_LE_CS_TEST_END 0x2096
/* ---- HCI Events ---- */
struct hci_ev_status {
__u8 status;
@ -2960,6 +3169,129 @@ struct hci_evt_le_read_all_remote_features_complete {
__u8 features[248];
} __packed;
/* Channel Sounding Events */
#define HCI_EVT_LE_CS_READ_RMT_SUPP_CAP_COMPLETE 0x2C
struct hci_evt_le_cs_read_rmt_supp_cap_complete {
__u8 status;
__le16 handle;
__u8 num_configs_supp;
__le16 max_consec_proc_supp;
__u8 num_ant_supp;
__u8 max_ant_path_supp;
__u8 roles_supp;
__u8 modes_supp;
__u8 rtt_cap;
__u8 rtt_aa_only_n;
__u8 rtt_sounding_n;
__u8 rtt_rand_payload_n;
__le16 nadm_sounding_cap;
__le16 nadm_rand_cap;
__u8 cs_sync_phys_supp;
__le16 sub_feat_supp;
__le16 t_ip1_times_supp;
__le16 t_ip2_times_supp;
__le16 t_fcs_times_supp;
__le16 t_pm_times_supp;
__u8 t_sw_times_supp;
__u8 tx_snr_cap;
} __packed;
#define HCI_EVT_LE_CS_READ_RMT_FAE_TABLE_COMPLETE 0x2D
struct hci_evt_le_cs_read_rmt_fae_table_complete {
__u8 status;
__le16 handle;
__u8 remote_fae_table[72];
} __packed;
#define HCI_EVT_LE_CS_SECURITY_ENABLE_COMPLETE 0x2E
struct hci_evt_le_cs_security_enable_complete {
__u8 status;
__le16 handle;
} __packed;
#define HCI_EVT_LE_CS_CONFIG_COMPLETE 0x2F
struct hci_evt_le_cs_config_complete {
__u8 status;
__le16 handle;
__u8 config_id;
__u8 action;
__u8 main_mode_type;
__u8 sub_mode_type;
__u8 min_main_mode_steps;
__u8 max_main_mode_steps;
__u8 main_mode_rep;
__u8 mode_0_steps;
__u8 role;
__u8 rtt_type;
__u8 cs_sync_phy;
__u8 channel_map[10];
__u8 channel_map_rep;
__u8 channel_sel_type;
__u8 ch3c_shape;
__u8 ch3c_jump;
__u8 reserved;
__u8 t_ip1_time;
__u8 t_ip2_time;
__u8 t_fcs_time;
__u8 t_pm_time;
} __packed;
#define HCI_EVT_LE_CS_PROCEDURE_ENABLE_COMPLETE 0x30
struct hci_evt_le_cs_procedure_enable_complete {
__u8 status;
__le16 handle;
__u8 config_id;
__u8 state;
__u8 tone_ant_config_sel;
__s8 sel_tx_pwr;
__u8 sub_evt_len[3];
__u8 sub_evts_per_evt;
__le16 sub_evt_intrvl;
__le16 evt_intrvl;
__le16 proc_intrvl;
__le16 proc_counter;
__le16 max_proc_len;
} __packed;
#define HCI_EVT_LE_CS_SUBEVENT_RESULT 0x31
struct hci_evt_le_cs_subevent_result {
__le16 handle;
__u8 config_id;
__le16 start_acl_conn_evt_counter;
__le16 proc_counter;
__le16 freq_comp;
__u8 ref_pwr_lvl;
__u8 proc_done_status;
__u8 subevt_done_status;
__u8 abort_reason;
__u8 num_ant_paths;
__u8 num_steps_reported;
__u8 step_mode[0]; /* depends on num_steps_reported */
__u8 step_channel[0]; /* depends on num_steps_reported */
__u8 step_data_length[0]; /* depends on num_steps_reported */
__u8 step_data[0]; /* depends on num_steps_reported */
} __packed;
#define HCI_EVT_LE_CS_SUBEVENT_RESULT_CONTINUE 0x32
struct hci_evt_le_cs_subevent_result_continue {
__le16 handle;
__u8 config_id;
__u8 proc_done_status;
__u8 subevt_done_status;
__u8 abort_reason;
__u8 num_ant_paths;
__u8 num_steps_reported;
__u8 step_mode[0]; /* depends on num_steps_reported */
__u8 step_channel[0]; /* depends on num_steps_reported */
__u8 step_data_length[0]; /* depends on num_steps_reported */
__u8 step_data[0]; /* depends on num_steps_reported */
} __packed;
#define HCI_EVT_LE_CS_TEST_END_COMPLETE 0x33
struct hci_evt_le_cs_test_end_complete {
__u8 status;
} __packed;
#define HCI_EV_VENDOR 0xff
/* Internal events generated by Bluetooth stack */

View File

@ -730,6 +730,8 @@ struct hci_conn {
__u16 le_per_adv_data_offset;
__u8 le_adv_phy;
__u8 le_adv_sec_phy;
__u8 le_tx_def_phys;
__u8 le_rx_def_phys;
__u8 le_tx_phy;
__u8 le_rx_phy;
__s8 rssi;
@ -2071,6 +2073,12 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
#define ll_ext_feature_capable(dev) \
((dev)->le_features[7] & HCI_LE_LL_EXT_FEATURE)
/* Channel sounding support */
#define le_cs_capable(dev) \
((dev)->le_features[5] & HCI_LE_CS)
#define le_cs_host_capable(dev) \
((dev)->le_features[5] & HCI_LE_CS_HOST)
#define mws_transport_config_capable(dev) (((dev)->commands[30] & 0x08) && \
(!hci_test_quirk((dev), HCI_QUIRK_BROKEN_MWS_TRANSPORT_CONFIG)))
@ -2334,6 +2342,7 @@ void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode);
void *hci_recv_event_data(struct hci_dev *hdev, __u8 event);
u32 hci_conn_get_phy(struct hci_conn *conn);
int hci_conn_set_phy(struct hci_conn *conn, u32 phys);
/* ----- HCI Sockets ----- */
void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb);

View File

@ -191,3 +191,6 @@ int hci_connect_big_sync(struct hci_dev *hdev, struct hci_conn *conn);
int hci_past_sync(struct hci_conn *conn, struct hci_conn *le);
int hci_le_read_remote_features(struct hci_conn *conn);
int hci_acl_change_pkt_type(struct hci_conn *conn, u16 pkt_type);
int hci_le_set_phy(struct hci_conn *conn, u8 tx_phys, u8 rx_phys);

View File

@ -655,8 +655,7 @@ struct l2cap_conn {
struct sk_buff *rx_skb;
__u32 rx_len;
__u8 tx_ident;
struct mutex ident_lock;
struct ida tx_ida;
struct sk_buff_head pending_rx;
struct work_struct pending_rx_work;

View File

@ -1002,12 +1002,18 @@ static struct hci_conn *__hci_conn_add(struct hci_dev *hdev, int type,
switch (type) {
case ACL_LINK:
conn->pkt_type = hdev->pkt_type & ACL_PTYPE_MASK;
conn->link_policy = hdev->link_policy;
conn->mtu = hdev->acl_mtu;
break;
case LE_LINK:
/* conn->src should reflect the local identity address */
hci_copy_identity_address(hdev, &conn->src, &conn->src_type);
conn->mtu = hdev->le_mtu ? hdev->le_mtu : hdev->acl_mtu;
/* Use the controller supported PHYS as default until the
* remote features are resolved.
*/
conn->le_tx_def_phys = hdev->le_tx_def_phys;
conn->le_rx_def_phys = hdev->le_tx_def_phys;
break;
case CIS_LINK:
/* conn->src should reflect the local identity address */
@ -1819,7 +1825,7 @@ static int hci_le_create_big(struct hci_conn *conn, struct bt_iso_qos *qos)
cp.bis.sdu = cpu_to_le16(qos->bcast.out.sdu);
cp.bis.latency = cpu_to_le16(qos->bcast.out.latency);
cp.bis.rtn = qos->bcast.out.rtn;
cp.bis.phy = qos->bcast.out.phy;
cp.bis.phy = qos->bcast.out.phys;
cp.bis.packing = qos->bcast.packing;
cp.bis.framing = qos->bcast.framing;
cp.bis.encryption = qos->bcast.encryption;
@ -1869,10 +1875,10 @@ static int set_cig_params_sync(struct hci_dev *hdev, void *data)
cis->cis_id = cis_id;
cis->c_sdu = cpu_to_le16(conn->iso_qos.ucast.out.sdu);
cis->p_sdu = cpu_to_le16(conn->iso_qos.ucast.in.sdu);
cis->c_phy = qos->ucast.out.phy ? qos->ucast.out.phy :
qos->ucast.in.phy;
cis->p_phy = qos->ucast.in.phy ? qos->ucast.in.phy :
qos->ucast.out.phy;
cis->c_phys = qos->ucast.out.phys ? qos->ucast.out.phys :
qos->ucast.in.phys;
cis->p_phys = qos->ucast.in.phys ? qos->ucast.in.phys :
qos->ucast.out.phys;
cis->c_rtn = qos->ucast.out.rtn;
cis->p_rtn = qos->ucast.in.rtn;
}
@ -1974,8 +1980,8 @@ struct hci_conn *hci_bind_cis(struct hci_dev *hdev, bdaddr_t *dst,
return cis;
/* Update LINK PHYs according to QoS preference */
cis->le_tx_phy = qos->ucast.out.phy;
cis->le_rx_phy = qos->ucast.in.phy;
cis->le_tx_phy = qos->ucast.out.phys;
cis->le_rx_phy = qos->ucast.in.phys;
/* If output interval is not set use the input interval as it cannot be
* 0x000000.
@ -2090,15 +2096,15 @@ int hci_le_create_cis_pending(struct hci_dev *hdev)
}
static void hci_iso_qos_setup(struct hci_dev *hdev, struct hci_conn *conn,
struct bt_iso_io_qos *qos, __u8 phy)
struct bt_iso_io_qos *qos, __u8 phys)
{
/* Only set MTU if PHY is enabled */
if (!qos->sdu && qos->phy)
if (!qos->sdu && qos->phys)
qos->sdu = conn->mtu;
/* Use the same PHY as ACL if set to any */
if (qos->phy == BT_ISO_PHY_ANY)
qos->phy = phy;
if (qos->phys == BT_ISO_PHY_ANY)
qos->phys = phys;
/* Use LE ACL connection interval if not set */
if (!qos->interval)
@ -2118,7 +2124,7 @@ static int create_big_sync(struct hci_dev *hdev, void *data)
u32 flags = 0;
int err;
if (qos->bcast.out.phy == 0x02)
if (qos->bcast.out.phys == BIT(1))
flags |= MGMT_ADV_FLAG_SEC_2M;
/* Align intervals */
@ -2227,8 +2233,7 @@ struct hci_conn *hci_bind_bis(struct hci_dev *hdev, bdaddr_t *dst, __u8 sid,
return conn;
/* Update LINK PHYs according to QoS preference */
conn->le_tx_phy = qos->bcast.out.phy;
conn->le_tx_phy = qos->bcast.out.phy;
conn->le_tx_def_phys = qos->bcast.out.phys;
/* Add Basic Announcement into Peridic Adv Data if BASE is set */
if (base_len && base) {
@ -2237,7 +2242,7 @@ struct hci_conn *hci_bind_bis(struct hci_dev *hdev, bdaddr_t *dst, __u8 sid,
}
hci_iso_qos_setup(hdev, conn, &qos->bcast.out,
conn->le_tx_phy ? conn->le_tx_phy :
conn->le_tx_def_phys ? conn->le_tx_def_phys :
hdev->le_tx_def_phys);
conn->iso_qos = *qos;
@ -2357,9 +2362,11 @@ struct hci_conn *hci_connect_cis(struct hci_dev *hdev, bdaddr_t *dst,
return le;
hci_iso_qos_setup(hdev, le, &qos->ucast.out,
le->le_tx_phy ? le->le_tx_phy : hdev->le_tx_def_phys);
le->le_tx_def_phys ? le->le_tx_def_phys :
hdev->le_tx_def_phys);
hci_iso_qos_setup(hdev, le, &qos->ucast.in,
le->le_rx_phy ? le->le_rx_phy : hdev->le_rx_def_phys);
le->le_rx_def_phys ? le->le_rx_def_phys :
hdev->le_rx_def_phys);
cis = hci_bind_cis(hdev, dst, dst_type, qos, timeout);
if (IS_ERR(cis)) {
@ -2614,8 +2621,8 @@ void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active)
timer:
if (hdev->idle_timeout > 0)
queue_delayed_work(hdev->workqueue, &conn->idle_work,
msecs_to_jiffies(hdev->idle_timeout));
mod_delayed_work(hdev->workqueue, &conn->idle_work,
msecs_to_jiffies(hdev->idle_timeout));
}
/* Drop all connection on the device */
@ -2928,22 +2935,22 @@ u32 hci_conn_get_phy(struct hci_conn *conn)
break;
case LE_LINK:
if (conn->le_tx_phy & HCI_LE_SET_PHY_1M)
if (conn->le_tx_def_phys & HCI_LE_SET_PHY_1M)
phys |= BT_PHY_LE_1M_TX;
if (conn->le_rx_phy & HCI_LE_SET_PHY_1M)
if (conn->le_rx_def_phys & HCI_LE_SET_PHY_1M)
phys |= BT_PHY_LE_1M_RX;
if (conn->le_tx_phy & HCI_LE_SET_PHY_2M)
if (conn->le_tx_def_phys & HCI_LE_SET_PHY_2M)
phys |= BT_PHY_LE_2M_TX;
if (conn->le_rx_phy & HCI_LE_SET_PHY_2M)
if (conn->le_rx_def_phys & HCI_LE_SET_PHY_2M)
phys |= BT_PHY_LE_2M_RX;
if (conn->le_tx_phy & HCI_LE_SET_PHY_CODED)
if (conn->le_tx_def_phys & HCI_LE_SET_PHY_CODED)
phys |= BT_PHY_LE_CODED_TX;
if (conn->le_rx_phy & HCI_LE_SET_PHY_CODED)
if (conn->le_rx_def_phys & HCI_LE_SET_PHY_CODED)
phys |= BT_PHY_LE_CODED_RX;
break;
@ -2952,6 +2959,111 @@ u32 hci_conn_get_phy(struct hci_conn *conn)
return phys;
}
static u16 bt_phy_pkt_type(struct hci_conn *conn, u32 phys)
{
u16 pkt_type = conn->pkt_type;
if (phys & BT_PHY_BR_1M_3SLOT)
pkt_type |= HCI_DM3 | HCI_DH3;
else
pkt_type &= ~(HCI_DM3 | HCI_DH3);
if (phys & BT_PHY_BR_1M_5SLOT)
pkt_type |= HCI_DM5 | HCI_DH5;
else
pkt_type &= ~(HCI_DM5 | HCI_DH5);
if (phys & BT_PHY_EDR_2M_1SLOT)
pkt_type &= ~HCI_2DH1;
else
pkt_type |= HCI_2DH1;
if (phys & BT_PHY_EDR_2M_3SLOT)
pkt_type &= ~HCI_2DH3;
else
pkt_type |= HCI_2DH3;
if (phys & BT_PHY_EDR_2M_5SLOT)
pkt_type &= ~HCI_2DH5;
else
pkt_type |= HCI_2DH5;
if (phys & BT_PHY_EDR_3M_1SLOT)
pkt_type &= ~HCI_3DH1;
else
pkt_type |= HCI_3DH1;
if (phys & BT_PHY_EDR_3M_3SLOT)
pkt_type &= ~HCI_3DH3;
else
pkt_type |= HCI_3DH3;
if (phys & BT_PHY_EDR_3M_5SLOT)
pkt_type &= ~HCI_3DH5;
else
pkt_type |= HCI_3DH5;
return pkt_type;
}
static int bt_phy_le_phy(u32 phys, u8 *tx_phys, u8 *rx_phys)
{
if (!tx_phys || !rx_phys)
return -EINVAL;
*tx_phys = 0;
*rx_phys = 0;
if (phys & BT_PHY_LE_1M_TX)
*tx_phys |= HCI_LE_SET_PHY_1M;
if (phys & BT_PHY_LE_1M_RX)
*rx_phys |= HCI_LE_SET_PHY_1M;
if (phys & BT_PHY_LE_2M_TX)
*tx_phys |= HCI_LE_SET_PHY_2M;
if (phys & BT_PHY_LE_2M_RX)
*rx_phys |= HCI_LE_SET_PHY_2M;
if (phys & BT_PHY_LE_CODED_TX)
*tx_phys |= HCI_LE_SET_PHY_CODED;
if (phys & BT_PHY_LE_CODED_RX)
*rx_phys |= HCI_LE_SET_PHY_CODED;
return 0;
}
int hci_conn_set_phy(struct hci_conn *conn, u32 phys)
{
u8 tx_phys, rx_phys;
switch (conn->type) {
case SCO_LINK:
case ESCO_LINK:
return -EINVAL;
case ACL_LINK:
/* Only allow setting BR/EDR PHYs if link type is ACL */
if (phys & ~BT_PHY_BREDR_MASK)
return -EINVAL;
return hci_acl_change_pkt_type(conn,
bt_phy_pkt_type(conn, phys));
case LE_LINK:
/* Only allow setting LE PHYs if link type is LE */
if (phys & ~BT_PHY_LE_MASK)
return -EINVAL;
if (bt_phy_le_phy(phys, &tx_phys, &rx_phys))
return -EINVAL;
return hci_le_set_phy(conn, tx_phys, rx_phys);
default:
return -EINVAL;
}
}
static int abort_conn_sync(struct hci_dev *hdev, void *data)
{
struct hci_conn *conn = data;

View File

@ -117,6 +117,7 @@ bool hci_discovery_active(struct hci_dev *hdev)
return false;
}
}
EXPORT_SYMBOL(hci_discovery_active);
void hci_discovery_set_state(struct hci_dev *hdev, int state)
{

View File

@ -2869,6 +2869,31 @@ static void hci_cs_le_ext_create_conn(struct hci_dev *hdev, u8 status)
hci_dev_unlock(hdev);
}
static void hci_cs_le_set_phy(struct hci_dev *hdev, u8 status)
{
struct hci_cp_le_set_phy *cp;
struct hci_conn *conn;
bt_dev_dbg(hdev, "status 0x%2.2x", status);
if (status)
return;
cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_PHY);
if (!cp)
return;
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
if (conn) {
conn->le_tx_def_phys = cp->tx_phys;
conn->le_rx_def_phys = cp->rx_phys;
}
hci_dev_unlock(hdev);
}
static void hci_cs_le_read_remote_features(struct hci_dev *hdev, u8 status)
{
struct hci_cp_le_read_remote_features *cp;
@ -4359,6 +4384,7 @@ static const struct hci_cs {
HCI_CS(HCI_OP_LE_CREATE_CONN, hci_cs_le_create_conn),
HCI_CS(HCI_OP_LE_READ_REMOTE_FEATURES, hci_cs_le_read_remote_features),
HCI_CS(HCI_OP_LE_START_ENC, hci_cs_le_start_enc),
HCI_CS(HCI_OP_LE_SET_PHY, hci_cs_le_set_phy),
HCI_CS(HCI_OP_LE_EXT_CREATE_CONN, hci_cs_le_ext_create_conn),
HCI_CS(HCI_OP_LE_CREATE_CIS, hci_cs_le_create_cis),
HCI_CS(HCI_OP_LE_CREATE_BIG, hci_cs_le_create_big),
@ -6607,8 +6633,20 @@ static void hci_le_remote_feat_complete_evt(struct hci_dev *hdev, void *data,
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
if (conn) {
if (!ev->status)
memcpy(conn->features[0], ev->features, 8);
if (!ev->status) {
memcpy(conn->le_features, ev->features, 8);
/* Update supported PHYs */
if (!(conn->le_features[1] & HCI_LE_PHY_2M)) {
conn->le_tx_def_phys &= ~HCI_LE_SET_PHY_2M;
conn->le_rx_def_phys &= ~HCI_LE_SET_PHY_2M;
}
if (!(conn->le_features[1] & HCI_LE_PHY_CODED)) {
conn->le_tx_def_phys &= ~HCI_LE_SET_PHY_CODED;
conn->le_rx_def_phys &= ~HCI_LE_SET_PHY_CODED;
}
}
if (conn->state == BT_CONFIG) {
__u8 status;
@ -6829,6 +6867,21 @@ static void hci_le_phy_update_evt(struct hci_dev *hdev, void *data,
hci_dev_unlock(hdev);
}
/* Convert LE PHY to QoS PHYs */
static u8 le_phy_qos(u8 phy)
{
switch (phy) {
case 0x01:
return HCI_LE_SET_PHY_1M;
case 0x02:
return HCI_LE_SET_PHY_2M;
case 0x03:
return HCI_LE_SET_PHY_CODED;
}
return 0;
}
static void hci_le_cis_established_evt(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
@ -6890,8 +6943,8 @@ static void hci_le_cis_established_evt(struct hci_dev *hdev, void *data,
1000);
qos->ucast.in.sdu = ev->c_bn ? le16_to_cpu(ev->c_mtu) : 0;
qos->ucast.out.sdu = ev->p_bn ? le16_to_cpu(ev->p_mtu) : 0;
qos->ucast.in.phy = ev->c_phy;
qos->ucast.out.phy = ev->p_phy;
qos->ucast.in.phys = le_phy_qos(ev->c_phy);
qos->ucast.out.phys = le_phy_qos(ev->p_phy);
break;
case HCI_ROLE_MASTER:
qos->ucast.in.interval = p_sdu_interval;
@ -6905,8 +6958,8 @@ static void hci_le_cis_established_evt(struct hci_dev *hdev, void *data,
1000);
qos->ucast.out.sdu = ev->c_bn ? le16_to_cpu(ev->c_mtu) : 0;
qos->ucast.in.sdu = ev->p_bn ? le16_to_cpu(ev->p_mtu) : 0;
qos->ucast.out.phy = ev->c_phy;
qos->ucast.in.phy = ev->p_phy;
qos->ucast.out.phys = le_phy_qos(ev->c_phy);
qos->ucast.in.phys = le_phy_qos(ev->p_phy);
break;
}
@ -7221,9 +7274,21 @@ static void hci_le_read_all_remote_features_evt(struct hci_dev *hdev,
if (!conn)
goto unlock;
if (!ev->status)
if (!ev->status) {
memcpy(conn->le_features, ev->features, 248);
/* Update supported PHYs */
if (!(conn->le_features[1] & HCI_LE_PHY_2M)) {
conn->le_tx_def_phys &= ~HCI_LE_SET_PHY_2M;
conn->le_rx_def_phys &= ~HCI_LE_SET_PHY_2M;
}
if (!(conn->le_features[1] & HCI_LE_PHY_CODED)) {
conn->le_tx_def_phys &= ~HCI_LE_SET_PHY_CODED;
conn->le_rx_def_phys &= ~HCI_LE_SET_PHY_CODED;
}
}
if (conn->state == BT_CONFIG) {
__u8 status;

View File

@ -2948,8 +2948,8 @@ static int hci_le_set_ext_scan_param_sync(struct hci_dev *hdev, u8 type,
if (conn) {
struct bt_iso_qos *qos = &conn->iso_qos;
if (qos->bcast.in.phy & BT_ISO_PHY_1M ||
qos->bcast.in.phy & BT_ISO_PHY_2M) {
if (qos->bcast.in.phys & BT_ISO_PHY_1M ||
qos->bcast.in.phys & BT_ISO_PHY_2M) {
cp->scanning_phys |= LE_SCAN_PHY_1M;
hci_le_scan_phy_params(phy, type,
interval,
@ -2958,7 +2958,7 @@ static int hci_le_set_ext_scan_param_sync(struct hci_dev *hdev, u8 type,
phy++;
}
if (qos->bcast.in.phy & BT_ISO_PHY_CODED) {
if (qos->bcast.in.phys & BT_ISO_PHY_CODED) {
cp->scanning_phys |= LE_SCAN_PHY_CODED;
hci_le_scan_phy_params(phy, type,
interval * 3,
@ -4428,6 +4428,17 @@ static int hci_le_set_event_mask_sync(struct hci_dev *hdev)
events[4] |= 0x02; /* LE BIG Info Advertising Report */
}
if (le_cs_capable(hdev)) {
/* Channel Sounding events */
events[5] |= 0x08; /* LE CS Read Remote Supported Cap Complete event */
events[5] |= 0x10; /* LE CS Read Remote FAE Table Complete event */
events[5] |= 0x20; /* LE CS Security Enable Complete event */
events[5] |= 0x40; /* LE CS Config Complete event */
events[5] |= 0x80; /* LE CS Procedure Enable Complete event */
events[6] |= 0x01; /* LE CS Subevent Result event */
events[6] |= 0x02; /* LE CS Subevent Result Continue event */
events[6] |= 0x04; /* LE CS Test End Complete event */
}
return __hci_cmd_sync_status(hdev, HCI_OP_LE_SET_EVENT_MASK,
sizeof(events), events, HCI_CMD_TIMEOUT);
}
@ -4560,23 +4571,43 @@ static int hci_set_le_support_sync(struct hci_dev *hdev)
}
/* LE Set Host Feature */
static int hci_le_set_host_feature_sync(struct hci_dev *hdev)
static int hci_le_set_host_feature_sync(struct hci_dev *hdev, u8 bit, u8 value)
{
struct hci_cp_le_set_host_feature cp;
if (!iso_capable(hdev))
return 0;
memset(&cp, 0, sizeof(cp));
/* Connected Isochronous Channels (Host Support) */
cp.bit_number = 32;
cp.bit_value = iso_enabled(hdev) ? 0x01 : 0x00;
cp.bit_number = bit;
cp.bit_value = value;
return __hci_cmd_sync_status(hdev, HCI_OP_LE_SET_HOST_FEATURE,
sizeof(cp), &cp, HCI_CMD_TIMEOUT);
}
/* Set Host Features, each feature needs to be sent separately since
* HCI_OP_LE_SET_HOST_FEATURE doesn't support setting all of them at once.
*/
static int hci_le_set_host_features_sync(struct hci_dev *hdev)
{
int err;
if (iso_capable(hdev)) {
/* Connected Isochronous Channels (Host Support) */
err = hci_le_set_host_feature_sync(hdev, 32,
(iso_enabled(hdev) ? 0x01 :
0x00));
if (err)
return err;
}
if (le_cs_capable(hdev))
/* Channel Sounding (Host Support) */
err = hci_le_set_host_feature_sync(hdev, 47, 0x01);
return err;
}
/* LE Controller init stage 3 command sequence */
static const struct hci_init_stage le_init3[] = {
/* HCI_OP_LE_SET_EVENT_MASK */
@ -4604,7 +4635,7 @@ static const struct hci_init_stage le_init3[] = {
/* HCI_OP_WRITE_LE_HOST_SUPPORTED */
HCI_INIT(hci_set_le_support_sync),
/* HCI_OP_LE_SET_HOST_FEATURE */
HCI_INIT(hci_le_set_host_feature_sync),
HCI_INIT(hci_le_set_host_features_sync),
{}
};
@ -6897,8 +6928,6 @@ static int hci_acl_create_conn_sync(struct hci_dev *hdev, void *data)
conn->attempt++;
conn->link_policy = hdev->link_policy;
memset(&cp, 0, sizeof(cp));
bacpy(&cp.bdaddr, &conn->dst);
cp.pscan_rep_mode = 0x02;
@ -7419,3 +7448,75 @@ int hci_le_read_remote_features(struct hci_conn *conn)
return err;
}
static void pkt_type_changed(struct hci_dev *hdev, void *data, int err)
{
struct hci_cp_change_conn_ptype *cp = data;
bt_dev_dbg(hdev, "err %d", err);
kfree(cp);
}
static int hci_change_conn_ptype_sync(struct hci_dev *hdev, void *data)
{
struct hci_cp_change_conn_ptype *cp = data;
return __hci_cmd_sync_status_sk(hdev, HCI_OP_CHANGE_CONN_PTYPE,
sizeof(*cp), cp,
HCI_EV_PKT_TYPE_CHANGE,
HCI_CMD_TIMEOUT, NULL);
}
int hci_acl_change_pkt_type(struct hci_conn *conn, u16 pkt_type)
{
struct hci_dev *hdev = conn->hdev;
struct hci_cp_change_conn_ptype *cp;
cp = kmalloc(sizeof(*cp), GFP_KERNEL);
if (!cp)
return -ENOMEM;
cp->handle = cpu_to_le16(conn->handle);
cp->pkt_type = cpu_to_le16(pkt_type);
return hci_cmd_sync_queue_once(hdev, hci_change_conn_ptype_sync, cp,
pkt_type_changed);
}
static void le_phy_update_complete(struct hci_dev *hdev, void *data, int err)
{
struct hci_cp_le_set_phy *cp = data;
bt_dev_dbg(hdev, "err %d", err);
kfree(cp);
}
static int hci_le_set_phy_sync(struct hci_dev *hdev, void *data)
{
struct hci_cp_le_set_phy *cp = data;
return __hci_cmd_sync_status_sk(hdev, HCI_OP_LE_SET_PHY,
sizeof(*cp), cp,
HCI_EV_LE_PHY_UPDATE_COMPLETE,
HCI_CMD_TIMEOUT, NULL);
}
int hci_le_set_phy(struct hci_conn *conn, u8 tx_phys, u8 rx_phys)
{
struct hci_dev *hdev = conn->hdev;
struct hci_cp_le_set_phy *cp;
cp = kmalloc(sizeof(*cp), GFP_KERNEL);
if (!cp)
return -ENOMEM;
memset(cp, 0, sizeof(*cp));
cp->handle = cpu_to_le16(conn->handle);
cp->tx_phys = tx_phys;
cp->rx_phys = rx_phys;
return hci_cmd_sync_queue_once(hdev, hci_le_set_phy_sync, cp,
le_phy_update_complete);
}

View File

@ -361,7 +361,7 @@ static int iso_connect_bis(struct sock *sk)
}
/* Fail if out PHYs are marked as disabled */
if (!iso_pi(sk)->qos.bcast.out.phy) {
if (!iso_pi(sk)->qos.bcast.out.phys) {
err = -EINVAL;
goto unlock;
}
@ -458,7 +458,7 @@ static int iso_connect_cis(struct sock *sk)
}
/* Fail if either PHYs are marked as disabled */
if (!iso_pi(sk)->qos.ucast.in.phy && !iso_pi(sk)->qos.ucast.out.phy) {
if (!iso_pi(sk)->qos.ucast.in.phys && !iso_pi(sk)->qos.ucast.out.phys) {
err = -EINVAL;
goto unlock;
}
@ -894,7 +894,7 @@ static struct proto iso_proto = {
.interval = 10000u, \
.latency = 10u, \
.sdu = 40u, \
.phy = BT_ISO_PHY_2M, \
.phys = BT_ISO_PHY_2M, \
.rtn = 2u, \
}
@ -1661,7 +1661,7 @@ static int iso_sock_recvmsg(struct socket *sock, struct msghdr *msg,
static bool check_io_qos(struct bt_iso_io_qos *qos)
{
/* If no PHY is enable SDU must be 0 */
if (!qos->phy && qos->sdu)
if (!qos->phys && qos->sdu)
return false;
if (qos->interval && (qos->interval < 0xff || qos->interval > 0xfffff))
@ -1670,7 +1670,7 @@ static bool check_io_qos(struct bt_iso_io_qos *qos)
if (qos->latency && (qos->latency < 0x05 || qos->latency > 0xfa0))
return false;
if (qos->phy > BT_ISO_PHY_ANY)
if (qos->phys > BT_ISO_PHY_ANY)
return false;
return true;

View File

@ -924,26 +924,18 @@ int l2cap_chan_check_security(struct l2cap_chan *chan, bool initiator)
initiator);
}
static u8 l2cap_get_ident(struct l2cap_conn *conn)
static int l2cap_get_ident(struct l2cap_conn *conn)
{
u8 id;
/* LE link does not support tools like l2ping so use the full range */
if (conn->hcon->type == LE_LINK)
return ida_alloc_range(&conn->tx_ida, 1, 255, GFP_ATOMIC);
/* Get next available identificator.
* 1 - 128 are used by kernel.
* 129 - 199 are reserved.
* 200 - 254 are used by utilities like l2ping, etc.
*/
mutex_lock(&conn->ident_lock);
if (++conn->tx_ident > 128)
conn->tx_ident = 1;
id = conn->tx_ident;
mutex_unlock(&conn->ident_lock);
return id;
return ida_alloc_range(&conn->tx_ida, 1, 128, GFP_ATOMIC);
}
static void l2cap_send_acl(struct l2cap_conn *conn, struct sk_buff *skb,
@ -1773,6 +1765,8 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err)
if (work_pending(&conn->pending_rx_work))
cancel_work_sync(&conn->pending_rx_work);
ida_destroy(&conn->tx_ida);
cancel_delayed_work_sync(&conn->id_addr_timer);
l2cap_unregister_all_users(conn);
@ -4782,12 +4776,34 @@ static int l2cap_le_connect_rsp(struct l2cap_conn *conn,
return err;
}
static void l2cap_put_ident(struct l2cap_conn *conn, u8 code, u8 id)
{
switch (code) {
case L2CAP_COMMAND_REJ:
case L2CAP_CONN_RSP:
case L2CAP_CONF_RSP:
case L2CAP_DISCONN_RSP:
case L2CAP_ECHO_RSP:
case L2CAP_INFO_RSP:
case L2CAP_CONN_PARAM_UPDATE_RSP:
case L2CAP_ECRED_CONN_RSP:
case L2CAP_ECRED_RECONF_RSP:
/* First do a lookup since the remote may send bogus ids that
* would make ida_free to generate warnings.
*/
if (ida_find_first_range(&conn->tx_ida, id, id) >= 0)
ida_free(&conn->tx_ida, id);
}
}
static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
struct l2cap_cmd_hdr *cmd, u16 cmd_len,
u8 *data)
{
int err = 0;
l2cap_put_ident(conn, cmd->code, cmd->ident);
switch (cmd->code) {
case L2CAP_COMMAND_REJ:
l2cap_command_rej(conn, cmd, cmd_len, data);
@ -5419,6 +5435,8 @@ static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
{
int err = 0;
l2cap_put_ident(conn, cmd->code, cmd->ident);
switch (cmd->code) {
case L2CAP_COMMAND_REJ:
l2cap_le_command_rej(conn, cmd, cmd_len, data);
@ -6907,13 +6925,13 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon)
hci_dev_test_flag(hcon->hdev, HCI_FORCE_BREDR_SMP)))
conn->local_fixed_chan |= L2CAP_FC_SMP_BREDR;
mutex_init(&conn->ident_lock);
mutex_init(&conn->lock);
INIT_LIST_HEAD(&conn->chan_l);
INIT_LIST_HEAD(&conn->users);
INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout);
ida_init(&conn->tx_ida);
skb_queue_head_init(&conn->pending_rx);
INIT_WORK(&conn->pending_rx_work, process_pending_rx);

View File

@ -885,7 +885,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
struct bt_power pwr;
struct l2cap_conn *conn;
int err = 0;
u32 opt;
u32 opt, phys;
u16 mtu;
u8 mode;
@ -1059,6 +1059,24 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
break;
case BT_PHY:
if (sk->sk_state != BT_CONNECTED) {
err = -ENOTCONN;
break;
}
err = copy_safe_from_sockptr(&phys, sizeof(phys), optval,
optlen);
if (err)
break;
if (!chan->conn)
break;
conn = chan->conn;
err = hci_conn_set_phy(conn->hcon, phys);
break;
case BT_MODE:
if (!enable_ecred) {
err = -ENOPROTOOPT;

View File

@ -1966,6 +1966,7 @@ static void set_ssp_complete(struct hci_dev *hdev, void *data, int err)
}
mgmt_cmd_status(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_err);
mgmt_pending_free(cmd);
return;
}
@ -1984,6 +1985,7 @@ static void set_ssp_complete(struct hci_dev *hdev, void *data, int err)
sock_put(match.sk);
hci_update_eir_sync(hdev);
mgmt_pending_free(cmd);
}
static int set_ssp_sync(struct hci_dev *hdev, void *data)
@ -6438,6 +6440,7 @@ static void set_advertising_complete(struct hci_dev *hdev, void *data, int err)
hci_dev_clear_flag(hdev, HCI_ADVERTISING);
settings_rsp(cmd, &match);
mgmt_pending_free(cmd);
new_settings(hdev, match.sk);

View File

@ -11,6 +11,12 @@
#include "mgmt_util.h"
#include "mgmt_config.h"
#define HDEV_PARAM_U32(_param_name_) \
struct {\
struct mgmt_tlv_hdr entry; \
__le32 value; \
} __packed _param_name_
#define HDEV_PARAM_U16(_param_name_) \
struct {\
struct mgmt_tlv_hdr entry; \
@ -29,6 +35,12 @@
cpu_to_le16(hdev->_param_name_) \
}
#define TLV_SET_U32(_param_code_, _param_name_) \
{ \
{ cpu_to_le16(_param_code_), sizeof(__u32) }, \
cpu_to_le32(hdev->_param_name_) \
}
#define TLV_SET_U8(_param_code_, _param_name_) \
{ \
{ cpu_to_le16(_param_code_), sizeof(__u8) }, \
@ -78,6 +90,7 @@ int read_def_system_config(struct sock *sk, struct hci_dev *hdev, void *data,
HDEV_PARAM_U16(advmon_allowlist_duration);
HDEV_PARAM_U16(advmon_no_filter_duration);
HDEV_PARAM_U8(enable_advmon_interleave_scan);
HDEV_PARAM_U32(idle_timeout);
} __packed rp = {
TLV_SET_U16(0x0000, def_page_scan_type),
TLV_SET_U16(0x0001, def_page_scan_int),
@ -111,6 +124,7 @@ int read_def_system_config(struct sock *sk, struct hci_dev *hdev, void *data,
TLV_SET_U16(0x001d, advmon_allowlist_duration),
TLV_SET_U16(0x001e, advmon_no_filter_duration),
TLV_SET_U8(0x001f, enable_advmon_interleave_scan),
TLV_SET_U32(0x0020, idle_timeout),
};
bt_dev_dbg(hdev, "sock %p", sk);
@ -122,6 +136,7 @@ int read_def_system_config(struct sock *sk, struct hci_dev *hdev, void *data,
}
#define TO_TLV(x) ((struct mgmt_tlv *)(x))
#define TLV_GET_LE32(tlv) le32_to_cpu(*((__le32 *)(TO_TLV(tlv)->value)))
#define TLV_GET_LE16(tlv) le16_to_cpu(*((__le16 *)(TO_TLV(tlv)->value)))
#define TLV_GET_U8(tlv) (*((__u8 *)(TO_TLV(tlv)->value)))
@ -191,6 +206,9 @@ int set_def_system_config(struct sock *sk, struct hci_dev *hdev, void *data,
case 0x001f:
exp_type_len = sizeof(u8);
break;
case 0x0020:
exp_type_len = sizeof(u32);
break;
default:
exp_type_len = 0;
bt_dev_warn(hdev, "unsupported parameter %u", type);
@ -314,6 +332,9 @@ int set_def_system_config(struct sock *sk, struct hci_dev *hdev, void *data,
case 0x0001f:
hdev->enable_advmon_interleave_scan = TLV_GET_U8(buffer);
break;
case 0x00020:
hdev->idle_timeout = TLV_GET_LE32(buffer);
break;
default:
bt_dev_warn(hdev, "unsupported parameter %u", type);
break;