mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-03-22 07:27:12 +08:00
Bluetooth: hci_conn: Fix using conn->le_{tx,rx}_phy as supported PHYs
conn->le_{tx,rx}_phy is not actually a bitfield as it set by
HCI_EV_LE_PHY_UPDATE_COMPLETE it is actually correspond to the current
PHY in use not what is supported by the controller, so this introduces
different fields (conn->le_{tx,rx}_def_phys) to track what PHYs are
supported by the connection.
Fixes: eab2404ba7 ("Bluetooth: Add BT_PHY socket option")
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -1008,6 +1008,11 @@ static struct hci_conn *__hci_conn_add(struct hci_dev *hdev, int type,
|
||||
/* 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 */
|
||||
@@ -2928,22 +2933,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;
|
||||
|
||||
@@ -6607,8 +6607,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;
|
||||
@@ -7221,9 +7233,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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user